function clone( clonedObject )
{
  if ( typeof( clonedObject ) != 'object' || clonedObject == null ) 
  {
    return clonedObject;
  }

  var newOjbect = new Object();

  for ( var i in clonedObject )
  {
    newOjbect[i] = clone( clonedObject[i] );
  }

  return newOjbect;
}

function objectsAreEqual( objectA, objectB )
{
  var areEqual = true;
  
  var countA = countB = 0;
  for ( key in objectA )
  {
    if ( objectA.hasOwnProperty( key ) )
    {
      countA += 1;
    }
  }
  
  for ( key in objectB )
  {
    if ( objectB.hasOwnProperty( key ) )
    {
      countB += 1;
    }
  }
  
  if ( countA !== countB )
  {
    return false;
  }
  
  $.each(objectB,function(index,value){
    if ( objectA[index] !== value )
    {
      if ( ( typeof( value ) == 'object' && typeof( objectA[index] ) == 'object' ) || ( typeof( value ) == 'array' && typeof( objectA[index] ) == 'array' ) )
      {
        areEqual = areEqual && objectsAreEqual( objectA[index], value );
      }
      else
      {
        areEqual = false;
      }
    }
  });
  
  return areEqual; 
};

RequestsSender = {
 
  selectedCount: 0,
  
  maxSelected: 0,
  
  maxFriendsPer: 0,

  Paginators: {},
  
  loadingIndicator: null,
  
  notificationSendWindow: null,
  
  isLoading: false,
  
  lastSearchTerm: '',
  
  states: { 
    all: { searchTerm: '', sort: 'first_name', page: 1, selectedFriends: {} }, 
    unselected: { searchTerm: '', sort: 'first_name', page: 1, selectedFriends: {} }
  },

  cleanState: { searchTerm: '', sort: 'first_name', page: 1, selectedFriends: {} },
  
  initialize: function()
  {
    RequestsSender.Paginators.all = new Paginator({ container: $('#RequestSender .paginator'), 
        callbackChangePageTo: RequestsSender.changePageTo,
        itemCount: $('#RequestSender .content.all .friendsCount').text(),
        itemsPerPage: 30
      });
    RequestsSender.Paginators.all.initialize();

    RequestsSender.loadingIndicator = $('#RequestSender .paginatorContainer img.loading');
    RequestsSender.maxSelected = parseInt( $('#RequestSender .requestsRemaining').text() );
    RequestsSender.maxFriendsPer = parseInt( $('#RequestSender .maxFriendsPer').text() );
    $('#RequestSender .content .friend').click(RequestsSender.friendClicked);
    $('#RequestSender .tabMenu li').click(RequestsSender.tabClicked);
    $('#RequestSender .selectedCount').text('0');
    $('#RequestSender button').click(RequestsSender.sendNotificationClick);
    $('#RequestSender .search input').keyup(RequestsSender.searchKeyUp);
    $('#RequestSender .search input').blur(RequestsSender.searchBlur);
    $('#RequestSender .sortContainer select').change(RequestsSender.changeToPageOne);
    $('#RequestSender .search .delete').click(function(){
      var searchInput = $('#RequestSender .search input');
      searchInput.val('Find Friends').addClass('noTerm');
      
      if ( '' != RequestsSender.lastSearchTerm )
      {
        RequestsSender.changeToPageOne();
      }
    });
    
    $('#RequestSender .search input').val('Find Friends').addClass('noTerm');
    $('#RequestSender .search input').click(function(){ 
      if ( $(this).hasClass('noTerm') ) { 
        $(this).val('').removeClass('noTerm'); 
      }
    });
  },
  
  hasFilteredResults: function()
  {
    return ( $('#RequestSender .search input').val() != 'Find Friends' ); 
  },
  
  friendClicked: function()
  {
    var selectedFrom = $('#RequestSender .tabMenu li.selected').attr('data-select');
    var userid = $(this).children('.id').text();
    if ( $(this).hasClass('selected') )
    {
      // Was selected, we're unselecting.
      $('#RequestSender .content.selected .friend.u' + userid).remove();
      $('#RequestSender .content .friend.u' + userid).removeClass('selected');
      delete RequestsSender.cleanState.selectedFriends['u' + userid];
      
      if ( selectedFrom != 'selected' )
      {
        delete RequestsSender.states[selectedFrom].selectedFriends['u' + userid];
      }
      
      RequestsSender.alterSelectedCount( -1 );
      
      $(this).removeClass('selected');
      
      if ( $('#RequestSender .content:visible').hasClass('selected') )
      {
        var friendCount = $('#RequestSender .content.selected div.friend').size();
        if ( friendCount == 0 )
        {
          $('#RequestSender .content.selected').html('<div class="noFriends">You deselected all of your friends! What will you do now?!</div>');
        }
      }
    } else {
      // Wasn't selected
      if ( RequestsSender.alterSelectedCount( 1 ) )
      {
        $('#RequestSender .content.selected .noFriends').remove();
        
        $(this).clone().appendTo('#RequestSender .content.selected').click(RequestsSender.friendClicked);
        RequestsSender.cleanState.selectedFriends['u' + userid] = true;
        RequestsSender.states[selectedFrom].selectedFriends['u' + userid] = true;

        if ( selectedFrom == 'unselected' )
        {
          var unselected = $('#RequestSender div.content.unselected');
          $(this).addClass('selected').hide();
          unselected.children('div.friend:not(.selected):lt(30)').show().click(RequestsSender.friendClicked);
          
          unselected.children('.friendsCount').text( parseInt( unselected.children('.friendsCount').text() - 1 ) );
          
          RequestsSender.Paginators.unselected.settings.itemCount = parseInt( unselected.children('.friendsCount').text() );
          RequestsSender.Paginators.unselected.buildPaginator();
          
          if ( unselected.children('div.friend:not(.selected)').size() == 0 && RequestsSender.Paginators.unselected.settings.page == 1 )
          {
            $('#RequestSender .content.unselected').html('<div class="noFriends">Your friends will thank you for this.</div>');
          }
        }
        $('#RequestSender .content .friend.u' + userid).addClass('selected');
      }
    }
  },
 
  selectSelected: function()
  {
    var isUnselectedSelected = ( $('#RequestSender .content:visible').hasClass('unselected') );
    $.each(RequestsSender.cleanState.selectedFriends,function(i,v)
      {
        if ( isUnselectedSelected === true )
        {
          $('#RequestSender .content:visible div.friend.' + i).addClass('selected').hide();
        } else {
          $('#RequestSender .content:visible div.friend.' + i).addClass('selected');
        }
      });
  },

  tabClicked: function()
  {
    if ( $(this).hasClass('selected') || RequestsSender.isLoading == true )
    {
      return false;
    }
    
    $('#RequestSender div.error').hide().appendTo('#RequestSender');
    
    var toSelect = $(this).attr('data-select');
    $('#RequestSender .content').addClass('hidden');
    $('#RequestSender .content.' + toSelect).removeClass('hidden');
    
    $(this).siblings().removeClass('selected').end().addClass('selected');
    
    if ( $(this).attr('data-select') == 'unselected' )
    {
      RequestsSender.resetFilters();
      $('#RequestSender div.paginator').show();
      if ( ! RequestsSender.Paginators.unselected )
      {
        RequestsSender.Paginators.unselected = new Paginator({ container: $('#RequestSender .paginator'), 
          callbackChangePageTo: RequestsSender.changePageTo,
          itemCount: ( parseInt( $('#RequestSender .content.all .friendsCount').text() ) - RequestsSender.selectedCount ),
          itemsPerPage: 30
        });
      }
      RequestsSender.Paginators.unselected.buildPaginator();
     
      if ( false == objectsAreEqual( RequestsSender.states.unselected, RequestsSender.cleanState ) || ! $('#RequestSender .content.unselected').html().replace(' ','') )
      {
        RequestsSender.resetFilters();
        $('#RequestSender .content.unselected').html('<div class="noFriends">Loading...</div>');
        RequestsSender.Paginators.unselected.buildPaginator();
        RequestsSender.changeToPageOne();
        RequestsSender.states.unselected = clone( RequestsSender.cleanState );
      }
      else
      {
        RequestsSender.Paginators.unselected.settings.page = 1;
        RequestsSender.Paginators.unselected.buildPaginator();
      }     
    } 
    else if ( $(this).attr('data-select') == 'selected' )
    {
      RequestsSender.resetFilters();
      $('#RequestSender div.paginator').hide();
      var friendCount = $('#RequestSender .content.selected div.friend').size();
      if ( friendCount == 0 )
      {
        $('#RequestSender .content.selected').html('<div class="noFriends">You don\'t have any friends selected.</div>');
      }
    } 
    else if ( $(this).attr('data-select') == 'all' )
    {
      RequestsSender.resetFilters();
      if ( false == objectsAreEqual( RequestsSender.states.all, RequestsSender.cleanState ) )
      {
        RequestsSender.Paginators.all.buildPaginator();
        RequestsSender.changeToPageOne();
        RequestsSender.states.all = clone( RequestsSender.cleanState );
      }
      else
      {
        RequestsSender.Paginators.all.settings.page = 1;
        RequestsSender.Paginators.all.buildPaginator();
      }
      $('#RequestSender div.paginator').show();
    }
  },
  
  displayError: function( errorMessage, timeout )
  {
    if ( RequestsSender.errorTimeout )
    {
      clearTimeout( RequestsSender.errorTimeout );
    }
      
    var errorBox = $('#RequestSender div.error').prependTo('#RequestSender .content:visible');
    errorBox.show().text(errorMessage);
    errorBox.css({ left: ( ( $('#RequestSender').width() / 2 ) - ( errorBox.width() / 2 ) ) + 'px' });
    RequestsSender.errorTimeout = setTimeout( RequestsSender.hideError, timeout );
  },
  
  hideError: function()
  {
    clearTimeout( RequestsSender.errorTimeout );
    $('#RequestSender .error').fadeOut('slow', function(){ $(this).appendTo('#RequestSender'); });
  },
  
  alterSelectedCount: function( difference )
  {
    if ( ( RequestsSender.selectedCount >= RequestsSender.maxSelected && difference >= 1 ) || ( RequestsSender.maxFriendsPer > 0 && RequestsSender.selectedCount >= RequestsSender.maxFriendsPer && difference >= 1 ) )
    {
      RequestsSender.displayError( 'You\'ve selected the maximum number of friends allowed.', 2500 );
      return false;
    }
    else {
      var remainingCount = ( RequestsSender.maxSelected - RequestsSender.selectedCount - difference );
      if ( remainingCount <= 3 && remainingCount != 0 )
      {
        $('#RequestSender .remainingWarning').text( 'Only ' + remainingCount + ' more...' );
      }
      else if ( remainingCount == 0 )
      {
        $('#RequestSender .remainingWarning').text( 'Limit is ' + RequestsSender.maxSelected );
      }
      else 
      {
        $('#RequestSender .remainingWarning').text( '' );
      }
      
      RequestsSender.selectedCount = RequestsSender.selectedCount + difference;
      $('#RequestSender .selectedCount').text( RequestsSender.selectedCount );
      return true;
    }
  },

  searchBlur: function()
  {
    if ( $(this).val() == '' )
    {
      $(this).val('Find Friends').addClass('noTerm');
    }
  },
  
  searchKeyUp: function()
  {
    var searchTerm = ( ! $('#RequestSender .search input').hasClass('noTerm') ) ? ( $('#RequestSender .search input').val() ) : ( '' );
    
    if ( searchTerm != RequestsSender.lastSearchTerm )
    {
      clearTimeout( RequestsSender.searchTimeout );
      RequestsSender.searchTimeout = setTimeout( RequestsSender.changeToPageOne, 300 );
    }
  },
  
  changeToPageOne: function()
  {
    var selected = $('#RequestSender .tabMenu li.selected').attr('data-select');

    paginator = RequestsSender.Paginators[selected];   
    paginator.settings.page = 1;
    paginator.buildPaginator();
    RequestsSender.changePageTo( 1, paginator );
  },
  
  resetFilters: function()
  {
    if ( $('#RequestSender .tabMenu li.selected').attr('data-select') == 'selected' )
    {
      $('#RequestSender .sortContainer').hide();
      $('#RequestSender .search').hide();
    }
    else
    {
      if ( $('#RequestSender .sortContainer select').val() != 'first_name' )
      {
        $('#RequestSender .sortContainer select').val('first_name');
      }
      $('#RequestSender .sortContainer').show();
      
      if ( $('#RequestSender .search input').val() != '' )
      {
        $('#RequestSender .search input').val('Find Friends').addClass('noTerm');
      }
      $('#RequestSender .search').show();
    }
  },
  
  changePageTo: function( pageNumber, Paginator )
  {
    $('#RequestSender div.error').hide().appendTo('#RequestSender');
    
    RequestsSender.showPageLoading();
    
    var ajaxURL = '/requests/friends';
    if ( typeof( SERVICE_NAME ) == 'undefined' )
    {
      ajaxURL = '/apps' + ajaxURL;
    }
    
    var dataObj = { page: pageNumber };
    if ( $('#RequestSender .content:visible').hasClass('unselected') )
    {
      dataObj.exceptions = RequestsSender.buildFriendsString();
    }
    
    var selectedTabName = $('#RequestSender .tabMenu li.selected').attr('data-select');
    
    dataObj.searchTerm = ( ! $('#RequestSender .search input').hasClass('noTerm') ) ? ( $('#RequestSender .search input').val() ) : ( '' );
    RequestsSender.lastSearchTerm = dataObj.searchTerm;
    dataObj.orderBy = $('#RequestSender .sortContainer select').val();
    dataObj.needsBuffer = ( selectedTabName == 'unselected' );
    dataObj.rid = $('#RequestSender .rid').text();
        
    $.ajax({
      url: ajaxURL,
      data: dataObj,
      dataType: 'json',
      type: 'post',
      success: function(data)
      {
        var visibleContent = $('#RequestSender .content:visible');
        visibleContent.html( data.content );
        visibleContent.children('div.friend').click(RequestsSender.friendClicked).parent().children('div.friend:gt(29)').hide();

        RequestsSender.states[selectedTabName].page = pageNumber;
        RequestsSender.states[selectedTabName].searchTerm = dataObj.searchTerm;
        RequestsSender.states[selectedTabName].sort = dataObj.orderBy;

        Paginator.settings.itemCount = parseInt( visibleContent.children('.friendsCount').text() );

        if ( Paginator.settings.itemCount == 0 && dataObj.searchTerm != '' )
        {
          $('#RequestSender .content:visible').html('<div class="noFriends">None of your friends match the search term "' + dataObj.searchTerm + '"</div>');
        }

        Paginator.buildPaginator();
        RequestsSender.selectSelected();
        RequestsSender.hidePageLoading();
      }
    });
  },
  
  sendNotificationClick: function()
  {
    if ( RequestsSender.selectedCount == 0 )
    {
      RequestsSender.displayError( 'You must select someone to send a Matching Donation Request to.', 3000 );
      return false;
    }
    
    RequestsSender.notificationSendWindow = $('<div/>').appendTo('body').dragonDrop({
      curtain: true,
      title: 'Send Notification',
      draggable: false,
      type: 'window',
      displayClass: 'dragonWhite SendNotification',
      content: $('#RequestSender .notificationBlock').html(),
      enableMinMax: false,
      width: '400'
    });
    
    RequestsSender.notificationSendWindow.find('textarea').keypress(function(){     
      if ( $(this).val().length >= 200 )
      {
        $(this).val( $(this).val().substring( 0, 200 ) );
      }
    });
    RequestsSender.notificationSendWindow.find('img.send').click(RequestsSender.sendNotification);
    RequestsSender.notificationSendWindow.find('div.controls img').click(function(){ RequestsSender.notificationSendWindow.find('.btn.close').trigger('click'); });
  },
  
  showPageLoading: function()
  {
    RequestsSender.loadingIndicator.show();
    $('#RequestSender .content:visible').html('<div class="noFriends">Loading...</div>');
    $('#RequestSender .tabMenu').addClass('loading');
    RequestsSender.isLoading = true;
  },
  
  hidePageLoading: function()
  {
    RequestsSender.loadingIndicator.hide();
    RequestsSender.isLoading = false;
    $('#RequestSender .tabMenu').removeClass('loading');
  },
  
  buildFriendsString: function()
  {
    var strFriends = '';
    $.each(RequestsSender.cleanState.selectedFriends,function(i,v){
        strFriends = strFriends + ',' + i.substring(1);
      });
    strFriends = '[' + strFriends.substring(1) + ']';
    return strFriends;
  },
  
  sendNotification: function()
  {   
    var ajaxURL = '/requests/send';
    if ( typeof( SERVICE_NAME ) == 'undefined' )
    {
      ajaxURL = '/apps' + ajaxURL;
    }
    
    $.ajax({
      url: ajaxURL,
      data: { friends: RequestsSender.buildFriendsString(), uniqueID: $('#RequestSender .rid').text(), message: $('.SendNotification textarea[@name="message"]').val() },
      type: 'post',
      dataType: 'json',
      success: function(data) {
        var friends = $('#RequestSender .selected.content .friend.selected').clone();
        $('#RequestSender *').fadeOut(500);
        $('#RequestSender').animate({height:'0px'}, 500, function(){
          $(this).css('height','auto');
          $(this).html('');          
          var pluralAppend = ( RequestsSender.selectedCount > 1 ) ? ( 's' ) : ( '' );
          var wasWere = ( RequestsSender.selectedCount > 1 ) ? ( 'were' ) : ( 'was' );
          var completedNotifications = $('<div class="completedNotifications"><h2><span class="count">' + RequestsSender.selectedCount + '</span> notification' + pluralAppend + ' ' + wasWere + ' successfully sent to your friend' + pluralAppend + ':</h2></div>').hide().appendTo('#RequestSender');
          friends.appendTo(completedNotifications);
          completedNotifications.slideDown();
          completedNotifications.append('<div class="clear"></div>');
          
          friends.each(function(){
            $($(this).find('img')).after($('<a title="View Profile"/>').attr('href',$(this).find('.profileLink').text()));
            $(this).find('img,span.name').appendTo($(this).find('a'));
          });
        });
      }
    });
  },
  
  reset: function ()
  {
    RequestsSender.cleanState.selectedFriends = {};
    RequestsSender.states.all = RequestsSender.cleanState;
    RequestsSender.states.unselected = RequestsSender.cleanState;
    RequestsSender.selectedCount = 0;
  }
}

// Make Requests Work!
//$(document).ready(RequestsSender.initialize);
