/*
 * Modified pluggin, based on:
 *
 * Async Treeview 0.1 - Lazy-loading extension for Treeview
 *
 * http://bassistance.de/jquery-plugins/jquery-plugin-treeview/
 *
 * Copyright (c) 2007 JÃ¶rn Zaefferer
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id$
 *
 */

;(function($) {

var childContextType = new Array();
childContextType["COMMENT"] = "COMMENT";
childContextType["PICK"] = "COMMENT";
childContextType["RATING"] = "COMMENT";
childContextType["REJECT"] = "COMMENT";
childContextType["REVIEW"] = "COMMENT";
childContextType["BLURB"] = "COMMENT";
childContextType["VIDEO"] = "COMMENT";

function handleRedirectTo(response) {
  window.location = response.redirectTo;
}

function clearError(prefix, context, contextId) {
  var errors = $("#" + comments.getErrorId(prefix, context, contextId));
  if (errors.length != 0) {
    errors.html('&nbsp;');
  }
}

function handleError(response, prefix, context, contextId, container) {
  if (container.find('> ul > li').length == 1) {
    container.find('> ul').remove();
  }
  else {
    container.find('> ul > li > .placeholder:first').remove();
  }
  var errors = $("#" + comments.getErrorId(prefix, context, contextId));
  if (errors.length != 0 && response.errors) {
    var response_errors = new Array();
    if (response.errors['_GLOBAL_'] && response.errors['_GLOBAL_'].length != 0) {
      response_errors = response.errors['_GLOBAL_'];
    }
    $.each(response_errors, function(index, value) {
      var error = $(document.createElement('div'))
      .addClass('error')
      .html('ERROR: ' + value);
      errors.append(error);
    });
  }
}

function disableLink(ev) {
  // cancels the event
  ev.preventDefault();
  return false;
}

function prepare(settings, commentableId, prefix, context, contextId, element) {
  var form = element.find("form");
  form.bind("submit", {settings: settings, commentableId: commentableId, prefix: prefix, context: context, contextId: contextId}, saveComment);
  var input = form.find("input");
  input.hint().adjust();
  input.bind("focus keydown keypress keyup", function(){input.adjust()});
  var save = form.find(".save");
  save.bind("click", {settings: settings, commentableId: commentableId, prefix: prefix, context: context, contextId: contextId}, saveComment);
  var hide = element.find(".hide");
  hide.click(function(){
    var elem = $('#' + commentableId);
    comments.onMouseLeave(elem, prefix, context, contextId);
    elem.mouseleave(function(){
      comments.onMouseLeave($(this), prefix, context, contextId);
    });
    $('.comments-errors').html('');
    return false;
  });
}

function loadChildren(settings, commentableId, prefix, context, contextId) {
  var container = $("#" + comments.getId(prefix, context, contextId));
  var childList = container.removeClass("hasChildren").find("> ul");
  load(settings, commentableId, prefix, context, contextId, childList, container);
}

function validateSaveComment(content) {
  if (!content) {
    return "Please enter some content.";
  }
}

function saveComment(ev) {
  var settings = ev.data.settings;
  var commentableId = ev.data.commentableId;
  var prefix = ev.data.prefix;
  var context = ev.data.context;
  var contextId = ev.data.contextId;
  var parent = $("#" + comments.getId(prefix, context, contextId));
  var input = parent.find("input");
  var content = input.val();

  if (errors = validateSaveComment(content)) {
    alert(errors);
    return false;
  }

  var save = parent.find('> form > .save:first');
  save.storeEvents();
  save.unbind('click');
  save.bind('click', disableLink);
  save.addClass('disabled');

  createBranch(parent);
  $.ajax($.extend(true, {
    type: "POST",
		url: settings.url_new,
		dataType: "json",
		data: {
      content: content,
      contextType: context,
      contextId: contextId
		},
		success: function(response) {
      clearError(prefix, context, contextId);
      input.val("").hint().adjust();
      save.restoreEvents();
      save.unbind('click', disableLink);
      save.removeClass('disabled');
      if (response.redirectTo) {
        handleRedirectTo(response);
      }
      else if (response.error) {
        handleError(response, prefix, context, contextId, parent);
      }
      else {
        var commentsCount = comments.getCommentsCount(prefix, context, contextId);
        comments.setCommentsCount(commentableId, prefix, context, contextId, commentsCount + 1);
        var childList = parent.find('> ul');
        childList.find('> li > .placeholder:first').parent().remove();
        createCurrent(settings, commentableId, prefix, childContextType[context], response.comment.id, childList, response.comment, false);
        var grandParent = parent.parent();
        parent.addClass('open');
        grandParent.treeview({add: parent});
      }
    }
	}, settings.ajax));
  return false;
}

function createCurrent(settings, commentableId, prefix, context, contextId, parent, node, canReply) {
  var current = $("<li/>");
  var childAuthorId = node.authorId;
  var childAuthorName = node.authorName;
  var childContext = childContextType[node.context];
  var childContextId = node.id;
  var childContent = node.content;
  var canReply = node.canReply && GLOBALS.uid;
  var html =
    '<span class="comment-content">"' + childContent + '"</span>' +
    ' - ' +
    '<span class="name"><a href="' + GLOBALS.contextPath + '/viewSubject/' + childAuthorId + '">' + childAuthorName + '</a></span>' +
    ' ';
  if (canReply) {
    html += '<form class="enter-comment">' +
      '{ <input title="enter reply" type="text" name="comment-content"/> }' +
      ' ' +
      '<a href="#" class="save">save</a>' +
    '</form>' +
    '<span class="comments-errors" id="' +  comments.getErrorId(prefix, childContext, childContextId) + '"></span>';
  }
  var id = comments.getId(prefix, childContext, childContextId);
  current = current.attr("id", id).attr("class", "comment").html(html);
  prepare(settings, commentableId, prefix, childContext, childContextId, current);
  var placeholders = parent.find('> li > .placeholder').parent().remove();
  current.appendTo(parent);
  placeholders.appendTo(parent);
  return current;
}

function createBranch(parent, children) {
  var branch = parent.find("> ul");
  if (branch.length == 0) {
    branch = $("<ul/>").appendTo(parent);
  }
  if (!children) {
    var current = $("<li/>");
    current = current.html("<span class='placeholder'>&nbsp;</span>");
    current.appendTo(branch);
    current.addClass("hasChildren");
  }
  return branch;
}

function load(settings, commentableId, prefix, context, contextId, child, container) {
	function createNode(parent) {
    var current = createCurrent(settings, commentableId, prefix, context, contextId, parent, this);
		if (this.classes) {
			current.children("span").addClass(this.classes);
		}
		if (this.expanded) {
			current.addClass("open");
		}
    if (this.hasComments) {
      var branch = createBranch(current, this.children);
      if (this.children && this.children.length) {
        $.each(this.children, createNode, [branch]);
      }
    }
	}
	$.ajax($.extend(true, {
    type: "GET",
		url: settings.url,
		dataType: "json",
		data: {
      contextType: context,
      contextId: contextId
		},
		success: function(response) {
      clearError(prefix, context, contextId);
      if (response.redirectTo) {
        handleRedirectTo(response);
      }
      else if (response.error) {
        handleError(response, prefix, context, contextId, container);
      }
      else {
        if (!response.canReply) {
          container.find("> .enter-comment").remove();
          container.find("> .comments-errors").remove();
          if (response.comments.length == 0) {
            var commentable = $("#" + commentableId);
            commentable.unbind('mouseleave mouseover click');
            $("#" + comments.getCountId(prefix, context, contextId)).remove();
          }
        }
        comments.setCommentsCount(commentableId, prefix, context, contextId, response.comments.length);
        child.empty();
        response.comments.sort(function(a, b){
          return a.whenCreated - b.whenCreated;
        });
        $.each(response.comments, createNode, [child]);
        $(container).treeview({add: child});
      }
    }
	}, settings.ajax));
}

var proxied = $.fn.treeview;
$.fn.treeview = function(settings, commentableId, prefix, context, contextId) {
	if (!settings.url) {
		return proxied.apply(this, arguments);
	}
  prepare(settings, commentableId, prefix, context, contextId, this.parent());
  loadChildren(settings, commentableId, prefix, context, contextId);
	var userToggle = settings.toggle;
	return proxied.call(this, $.extend({}, settings, {
		collapsed: true,
		toggle: function() {
      var context = comments.getContext(this.id);
      loadChildren(settings, commentableId, prefix, context.type, context.id);
			if (userToggle) {
				userToggle.apply(this, arguments);
			}
		}
	}));
};

})(jQuery);
