// The "module" exported by this script is called "ngbundle":
// Applies drag and drop behaviour to templates/bundle

$(document).ready(function(){ 
  $('.bundle-handle.title').live('mouseover', function(){ //mouseenter
    // note: these little icons (.link-actions) are positioned absolute
    // relative to the span.bundle-container
    //first hide all open link actions
    if (littleIconsHover == false) { return; }
    $('.link-actions, .bundle-actions').hide()

    var bundleActions = $(this).parents('.bundle-container').find('.bundle-actions')
    bundleActions.show()
  }).live('mouseout',function(){ //mouseleave
    var that = this;
    var t = setTimeout(function(){$(that).parents('.bundle-container').find('.bundle-actions').fadeOut()}, 500)
    function bundleActionAMouseOver(e){
      clearTimeout(t)
      $(this).unbind('mouseover', bundleActionAMouseOver) //unbind yourself.
    }
    function bundleMouseOver(e) {
      clearTimeout(t)
      $(this).unbind('mouseover', bundleMouseOver)
    }
    $(this).mouseover(bundleMouseOver)
    $(this).parents('.bundle-container').find('.bundle-actions a').mouseover(bundleActionAMouseOver)
  })
  
  function bundleActionsMouseLeave() {
      var that = this
      clog('self destruct' + (new Date()).getTime())
      var k = setTimeout(function(){$(that).fadeOut()}, 500)
      function bundleActionsMouseEnter() {
          var that = this
          clearTimeout(k)
          $(this).unbind('mouseenter', bundleActionsMouseEnter)
      }
      function bundleMouseOver() {
        clearTimeout(k)
        $(this).unbind('mouseover', bundleMouseOver)
      }
      $(this).mouseenter(bundleActionsMouseEnter)
      $(this).parents('.bundle-container').find('.bundle-handle.title').mouseover(bundleMouseOver)
  }
  
  $('.bundle-actions').mouseleave(bundleActionsMouseLeave)
  //$('.bundle-actions').mouseenter(bundleActionsMouseEnter)
  
  // Code for creating a bundle
  // add bundle
  $('.create-bundle').click(function(){
    var newBundleLink = this
    var newBundleDialog = $('.new-bundle-dialog').eq(0).clone();
    var form = $(newBundleDialog).find("#new_bundle")
    
    function formSubmit(){
      clickOk()
      form.unbind('submit', formSubmit)
      return false;
    }
    
    form.submit(formSubmit)
    
    function clickOk() {
      createBundle()
      $(form).find('#bundle_display_name').val('')
      $(newBundleDialog).dialog("close");
      $(newBundleDialog).dialog("destroy");
    }
    
    clog($('.new-bundle-dialog'))
    newBundleDialog.dialog({ 
      bgiframe: true,
      autoOpen: true,
      modal: true,
      close: function() {
        $(this).remove()
      },
      buttons: { 
        "Ok": clickOk,
        "Cancel": function() {
          $(form).find('#bundle_display_name').val('')
          $(this).dialog("close");
          $(this).dialog("destroy");
        }
      }
    });
    return false;
    function createBundle() {
      var displayName = newBundleDialog.find('[name="bundle[display_name]"]').val()
      $.ajax({
        'type' : "POST",
        'url' : $(newBundleLink).attr('rel'),
        data : {
          'authenticity_token': form_authenticity_token,
          '_method' : 'POST',
          'bundle[name]' : 'sidebar', //for now we are only doing the sidebar
          'bundle[display_name]' : displayName
        }, success : function(data){
          clog(data)
          data = JSON.parse(data)
          var bundle = data.bundle
          clog(bundle)
          //when you change html here, also change it in bundle.liquid
          var  newBundle =
          $('    <li class="sortable-bundle">'
          + '      <span class="bundle-container">'
          + '        <a style="display: none;" class="data" rel="/bundles/'+bundle.id+'" id="'+bundle.id+'"></a>'
          + '        <div class="title bundle-handle" style="cursor: move;">'+bundle.display_name+'</div>'
          + '        <div style="display: none;" class="bundle-actions">'
          + '          <ul>'
          + '            <li><a class="ui-icon ui-icon-arrow-4 move-bundle-action bundle-handle" href="#" style="cursor: move;"></a></li>'
          + '            <li><a class="ui-icon ui-icon-plus new-link-action" href="/bundles/new" rel="/bundles/new"></a></li>'
          + '            <li><a rel="/bundles/'+bundle.id+'/edit" href="/bundles/'+bundle.id+'/edit" class="ui-icon ui-icon-pencil edit-bundle-action"></a></li>'
          + '            <li><a class="ui-icon ui-icon-trash destroy-bundle-action" href="/bundles/'+bundle.id+'" rel="/bundles/'+bundle.id+'"></a></li>'
          + '          </ul>'
          + '        </div>'
          + '        <ul class="ui-sortable link-list connected-links" unselectable="on" style="-moz-user-select: none;">'
          + '        '
          + '        </ul>'
          + '      </span>'
          + '    </li>');
        
          // The reason that the a new bundle dialog is being added is because existing code requires each
          // bundle to have its own dialog.
          var newBundleDialog = 
          $('    <div class="new-link-dialog" title="Create new link" style="display: none;">'
          + '    	<p id="validateTips">All form fields are required.</p>'
          + '      <form action="/links" class="new-link-form" method="post">'
          + '        <input name="authenticity_token" type="hidden" value="'+form_authenticity_token+'" />'
          + '        <input id="link_bundle_id" name="link[bundle_id]" type="hidden" value="'+bundle.id+'"/>'
          + '      	<fieldset>'
          + '      	  <p>'
          + '            <label for="link_display_text">Text to display</label>'
          + '            <input class="slug text ui-widget-content ui-corner-all" id="link_display_text" maxlength="200" name="link[display_text]" type="text" />'
          + '          </p>'
          + '          <p>'
          + '            <label for="link_link_type">Type</label>'
          + '            <span class="link_type">'
          + '              <span>Internal</span>'
          + '              <input class="text ui-widget-content ui-corner-all" checked="checked" id="link_type_internal" name="link_type" type="radio" value="internal" />'
          + '            </span>'
          + '          '
          + '            <span class="link_type">'
          + '              <span>External</span>'
          + '              <input class="text ui-widget-content ui-corner-all" id="link_type_external" name="link_type" type="radio" value="external" />'
          + '            </span>'
          + '          </p>'
          + '          <p id="internal">'
          + '            <label for="internal_url">Page</label>'
          + $('#pages-helper').html()
          + '          </p>'
          + ''
          + '          <p id="external">'
          + '            <label for="external_url">URL</label> '
          + '            <input class="text ui-widget-content ui-corner-all" id="external_url" name="external_url" type="text" />'
          + '          </p>'
          + ''
          + '          <!--<p id="new_page">'
          + '            <label for="new_page_title">Page title</label> <input class="text ui-widget-content ui-corner-all" id="new_page_title" name="new_page_title" type="text" />'
          + '          </p>-->'
          + '          <p>'
          + '            <label for="link_description">Tooltip</label>'
          + '            <input class="text ui-widget-content ui-corner-all" id="link_description" name="link[description]" type="text" />'
          + '          </p>'
          + '      	</fieldset>      	'
          + '    	</form>'
          + '    </div>')
        
          newBundle.find('.bundle-actions').mouseleave(bundleActionsMouseLeave)
          var linko = new nglink.Link
          linko.makeSortable(newBundle.find('ul'))
          $('.sidebar.bundle ul.bundle-list').append(newBundle).append(newBundleDialog)
        }
      })
    }
    return false;
  })
})


var ngbundle = function() {

function Bundle(bundle_list) {

  // Add 'new' if we were not called with 'new', so prototyping works.
  if(!(this instanceof Bundle)) {
    return new Bundle(bundle_list);
  }
  
  this._bundle_list = bundle_list;
  this._bundle_handle_selector = ".bundle-handle";
  this._bundle_sortable_selector = ".sortable-bundle"; // our bundle "object"

  clog("Bundle setup");
  clog(this._bundle_list);
}

/* Creates a POST to /bundle/id/move. The display_order is the destination */
Bundle.prototype.move_bundle = function(bundle, idx_dest) {
  var data = bundle.find("a.data");
  var display_order = idx_dest + 1;
  var id = data.attr("id");
  var rel = data.attr("rel");
  var url = rel + "/move";
  clog("Moving bundle " + data.attr("rel") + " to " + display_order);
  jQuery.post(url, {
    "authenticity_token": form_authenticity_token,
    "display_order": display_order,
    "id": id
  }, function(data, status) {
    clog("Moved bundle: " + status);
    clog(data);
  });
};

/* A +bundle+ is a <li class="sortable-bundle"> */
Bundle.prototype.delete_bundle = function(bundle) {
  var data = bundle.find("a.data");
  var rel = data.attr("rel");

  // clog(bundle);
  // clog(data);
  // clog(rel);

  jQuery.post(rel, {
    "_method": "delete",
    "authenticity_token": form_authenticity_token
  }, function(data, status) {
    bundle.fadeOut(function() {
      $(this).remove();
    });
  }, "script");
};

Bundle.prototype.new_link = function(form, success) {
  clog(form);
  form.ajaxSubmit({
    success: success
  });
  // form.find(".new_link").formSerialize();
  // clog(fields);
};

Bundle.prototype.enableSorting = function() {
  var self = this;
  var startAt, endAt = null;

  this._bundle_list.sortable({
    items: self._bundle_sortable_selector,
    placeholder: 'ui-state-highlight',
    handle: self._bundle_handle_selector,
    cursor: "move",
    revert: true,

    start: function(event, ui) {
      startAt = endAt = indexAt(self._bundle_list, ui.item);
      autofit(ui.placeholder, ui.item);
    },
    
    stop: function(event, ui) {
      endAt = indexAt(self._bundle_list, ui.item);
      if (startAt != endAt) {
        self.move_bundle(ui.item, endAt);
      }
    }
  });
};

Bundle.prototype.enableMenus = function() {
  
  var self = this;
  var menu = null;

  // Set the cursor type via JS. (Doing it in a stylesheet didn't work)
  this._bundle_list.find(this._bundle_handle_selector).css("cursor", "move");

  // TODO: How to make the bundle-actions stay open if the user moved from the title to the actions

  // Take 1. 
  // function checkHover() {
  //   console.log("calling check hover");
  //   if (menu) {
  //     menu.fadeOut("fast");
  //     menu = null;
  //   }
  // }
  // 
  // this._bundle_list.find("div.title")
  // .hover(
  //   function() {
  //     if (menu) {
  //       menu.fadeOut("fast");
  //       menu = null;
  //     }
  //     $(this).next(".bundle-actions").fadeIn("slow");
  //   },
  //   function() {
  //     menu = $(this).next(".bundle-actions");
  //     setTimeout(function() { checkHover(); }, 400);
  //   }
  // );

  // Take 2..
  // // Add hover behaviour and style to the handle selectors
  // this._bundle_list.find(this._bundle_handle_selector)
  // .hover(
  //   function() { 
  //     var bundle_actions = $(this).next(".bundle-actions");
  //     bundle_actions.fadeIn(100);
  //     bundle_actions.find(".move-bundle-action").addClass("ui-state-hover"); 
  //   },
  //   function() { 
  //     var bundle_actions = $(this).next(".bundle-actions");
  //     setTimeout(function() {
  //       // buggy
  //       bundle_actions.hide();
  //       bundle_actions.find(".move-bundle-action").removeClass("ui-state-hover"); 
  //     }, 2500);
  //   }
  // );
  
  // // Take 3
  // this.forEachSortableBundle(function(bundle) {
  //   bundle.find(".bundle-actions").hover(
  //     function() {}, 
  //     function() { $(this).hide(); }
  //   );
  // });
  // 
  // this.forEachSortableBundle(function(bundle) {
  //   bundle.find(".title.bundle-handle").hover(
  //     function() { 
  //       var bundle_actions = bundle.find(".bundle-actions");
  //       // $(this).find(".move-bundle-action").addClass("ui-state-hover"); 
  //       bundle_actions.show();
  //     }, 
  //     function() { 
  //       // $(this).find(".move-bundle-action").removeClass("ui-state-hover");
  //       // var bundle_actions = $(this).next(".bundle-actions");
  //       // bundle_actions.hide();
  //     }
  //   );
  // });


  $(".move-bundle-action, .new-link-action, .edit-bundle-action, .destroy-bundle-action").live('mouseover',function() {
    //not adding the hover sate if it is in the header or footer.
    if (!($(this).hasClass("header-footer") && $(this).hasClass("new-link-action"))) {
      $(this).addClass("ui-state-hover"); 
    }
  }).live('mouseout',
    function() {
      $(this).removeClass("ui-state-hover");
     }
  );
    

  // Add hover styles to the action icons
  this.forEachSortableBundle(function(bundle) {
    
  });

};

Bundle.prototype.enableActions = function() {
  
  var self = this;
  // Show "Create new link" dialog on click //add link
  $('.new-link-action').live('click', function(){
    var bundle = $(this).parents('.sortable-bundle')
    var bundleId = bundle.find('a.data').attr('id')
    var new_dialog = $('#link_bundle_id[value="'+bundleId+'"]').parents('.new-link-dialog')
    // This next line is commented out because it uses .next()
    // Which means after a bundle is moved .next() wont work unless the new-link-dialog
    // is also moved. Solution, just find the new-link-dialog based off the bundle id.
    // new_dialog = bundle.next(".new-link-dialog").clone()
    
    var form = $(new_dialog).find(".new-link-form");
      
    function formSubmit(){
      clickOk.call(new_dialog) //calling clickOk with *this* as the dialog
      form.unbind('submit',formSubmit)
      return false;
    }
        
    form.submit(formSubmit)
      
    function clickOk() {
      self.new_link(form, function(response, status) {
        console.log(response, status);
        response =  JSON.parse(response)
        link = response.link
        form.find('#link_display_text').val('')
        clog(bundle)
        //when you change html here, also change it in bundle.liquid
        new_link = $( '<li class="sortable-link">' +
                        '<a title="" rel="/links/'+link.id+'" href="'+link.url+'" class="link-handle link-click" style="cursor: move;">'+link.display_text+'</a>' +
                        '<div style="display: none;" class="link-actions">' +
                          '<ul>' +
                            '<li><a class="ui-icon ui-icon-arrow-4 move-link-action link-handle" href="#" style="cursor: move;"></a></li>' +
                            '<li><a rel="/links/'+link.id+'" class="ui-icon ui-icon-pencil edit-link-action" alt="Edit link" href="/links/'+link.id+'/edit">Edit</a></li>' + 
                            '<li><a rel="/links/'+link.id+'" class="ui-icon ui-icon-trash destroy-link-action" alt="Delete link" href="/links/'+link.id+'">Delete</a></li>' +
                          '</ul>' +
                        '</div>' +
                      '</li>')
        bundle.find('ul.link-list').append(new_link)
      });
      $(this).dialog("close");
      $(this).dialog("destroy"); 
    }
      
    
    new_dialog.dialog({
      bgiframe: true,
      autoOpen: false,
      height: 300,
      modal: true,
      width: 350,
      buttons: {
        "Ok": clickOk,
        "Cancel": function() {
          $(this).dialog("close");
        }
      }
    });
    new_dialog.dialog("open");
    return false;
  });

  // Show "Edit existing link" dialog on click
  // edit bundle
    $('.bundle-actions .edit-bundle-action').live('click', function(){
        var bundleId = $(this).parents('.sortable-bundle').find('a.data').attr('id')
        clog(bundleId)
        //cloning here because for some reason when I don't
        //after the user hits escape, or 'x', the dialog will never return
        var editBundleDialog = $('.new-bundle-dialog').clone();
        var form = $(editBundleDialog).find("#new_bundle")
        
        //fill the input box with what the label currently is.
        form.find('#bundle_display_name').val($(this).parents('.bundle-container').find('.title').text())
        
        function formSubmit(){
          clickOk()
          form.unbind('submit',formSubmit)
          return false;
        }
        
        form.submit(formSubmit)
        
        var pencil = this;
        function editBundle() {
          var displayName = editBundleDialog.find('[name="bundle[display_name]"]').val()
          $.ajax({
            'type' : "POST",
            'url' : '/bundles/' + bundleId + ".js",
            data : {
              'authenticity_token': form_authenticity_token,
              '_method' : 'PUT',
              'bundle[display_name]' : displayName
            }, success : function(data){
              data = JSON.parse(data)
              bundle = data.bundle
              $(pencil).parents('.bundle-container').find('.title').text(bundle.display_name)
            }
          })
        }
        
        function clickOk() {
          editBundle()
          $(form).find('#bundle_display_name').val('')
          form.unbind('submit',formSubmit)
          $(editBundleDialog).dialog("close");
          $(editBundleDialog).dialog("destroy");
        }

        editBundleDialog.dialog({
          title: "Edit Bundle", 
          bgiframe: true,
          autoOpen: true,
          modal: true,
          close: function() {
            $(this).remove()
          },
          buttons: { 
            "Ok": clickOk,
            "Cancel": function() {
              form.unbind('submit',formSubmit)
              $(this).dialog("close");
              $(this).dialog("destroy");
            }
          }
        });
        return false;
    });

  // Show "Destroy existing bundle" dialog on click  
  $('.bundle-actions .destroy-bundle-action').live('click', function(){
      var bundle = $(this).parents('.sortable-bundle')
      $("<div>Delete bundle and all links?</div>").dialog({ 
        title: "Delete?",
        buttons: { 
          "Ok": function() {
            self.delete_bundle(bundle); 
            $(this).dialog("close");
          },
          "Cancel": function() { 
            $(this).dialog("close");
          }
        }
      });
      return false;
  });
  
  
};

/* Helper function which applies a function to every <li class="sortable-bundle"> element */
Bundle.prototype.forEachSortableBundle = function(func) {
  this._bundle_list.find(this._bundle_sortable_selector).each(function() {
    var sortableBundle = $(this);
    func(sortableBundle);
  });
};

// Bundle.prototype.forEachBundleUnit = function(func) {
//   this._bundle_list.find(".bundle.unit").each(function() {
//     var bundleUnit = $(this);
//     bundleUnit.find(this._bundle_sortable_selector).each(function() {
//       var bundleItem = $(this);
//
//     })
//     func(bundleItem);
//   });
// };

/*
 Accepts only 
 <ul class="ui-sortable bundle-list">
 </ul>
 
 See bundle.liquid for details on the mark up
*/
Bundle.prototype.setup = function() {
  this.enableSorting();
  this.enableMenus();
  this.enableActions();
  // this._bundle_list.disableSelection();
};

/* Autofits the placeholder to the height&width of the item */
function autofit(placeholder, item) {
  jQuery(placeholder).height(item.outerHeight(true)).width(item.outerWidth(true));
}

function indexAt(bundles, bundle) {
  return bundles.children().index(bundle);
}

function logBundle(ui) {
  clog("Helper: ");
  clog(ui.helper);
  clog("Position: ");
  clog(ui.position);
  clog("Offset: ");
  clog(ui.offset);
  clog("Item: ");
  clog(ui.item);
  clog("PlaceHolder: ");
  clog(ui.placeholder);
  clog("Sender: ");
  clog(ui.sender);
}

return {Bundle: Bundle};

}();
