var Blog = {
  content: null,
  
  setupComments: function()
  {
    CommentManager.createAll(Blog.content);
    var base = $('main_comment_container');
    var subComments = $('main_entry_comments');
    if (base && subComments)
    {
      new CommentForm(base, subComments);
    }
  },
  
  load: function(event)
  {
    Blog.content = $('content');
    Blog.setupComments();
  }
}
Event.observe(window, 'load', Blog.load);

var CommentManager = {
  comments: [],
  hideAll: function()
  {
    CommentManager.comments.each(function(comment) {
      comment.hide();
    });
  },
  
  createAll: function(parentElement)
  {
    parentElement.select('.add_comment').each(function(holder){
      new AddCommentLink(holder);
    });
  },
  
  getFormValues: function(form)
  {
    var names = ['.add_comment_author', '.add_comment_url', '.add_comment_body', '.add_comment_secret'];
    return names.collect(
      function(name){
        var obj = form.select(name)[0];
        return {
          value: $F(obj), object: obj
        };
      }
    );
  }
};

var AddCommentLink = Class.create({
  initialize: function(addComment)
  {
    this.parentElement = Element.extend(addComment.parentNode);

    this.subCommentsContainer = this.parentElement.immediateDescendants().find(
      function(element) {
        return element.hasClassName('sub_comments');
      }
    );
    
    this.showLink = addComment.firstDescendant();
    Event.observe(this.showLink, 'click', this.onClickShow.bind(this));
    
    CommentManager.comments.push(this);
  },
  
  show: function()
  {
    if (! this.isHidden()) return;
    
    if (this.formHolder && ! this.effecting)
    {
      this.effecting = true;
      new Effect.BlindDown(this.formHolder, {
        duration: 0.5,
        afterFinish: this.finishEffect.bind(this)
      });
      this.showLink.addClassName('hide');
    }
  },
  
  hide: function(fast)
  {
    if (this.isHidden()) return;
    
    if (this.formHolder && ! this.effecting)
    {
      if (fast)
      {
        this.formHolder.hide();
      }
      else
      {
        this.effecting = true;
        new Effect.BlindUp(this.formHolder, {
          duration: 0.5,
          afterFinish: this.finishEffect.bind(this)
        });
      }
      this.showLink.removeClassName('hide');
    }
  },
  
  finishEffect: function() { this.effecting = false; },
  
  isHidden: function()
  {
    return ! this.showLink.hasClassName('hide');
  },
  
  onClickShow: function(event)
  {
    if (this.hasBeenLoaded())
    {
      if (this.isHidden())
      {
        CommentManager.hideAll();
        this.show();
      }
      else
      {
        this.hide();
      }
    }
    
    if (event) Event.stop(event);
  },

  onClickHide: function(event)
  {
    this.hide();    
    Event.stop(event);
  },
  
  hasBeenLoaded: function()
  {
    if (!this.requested)
    {
      this.requested = true;
      new Ajax.Request(this.showLink.href, {
        method: 'get',
        onSuccess: this.doLoad.bind(this),
        onFailure: (function() {
          this.requested = false;
        }).bind(this)
      });
    }
    return this.formHolder != null;
  },
  
  doLoad: function(xhr)
  {
    // Stick the responseText in a temp element first so we don't 
    // reinstantiate all the objects living in the parent element.
    var temp = new Element('div');
    temp.innerHTML += xhr.responseText;
    var container = temp.firstDescendant();
    
    this.attachFormEvents(container);
    
    this.formHolder.style.display = 'none';
    this.subCommentsContainer.appendChild(container);
    
    this.onClickShow();
  },
  
  attachFormEvents: function(container)
  {
    this.formHolder = container.select('.comment_form')[0];
    this.hideLink = container.select('.hide_comment_link')[0];
    
    Event.observe(this.hideLink, 'click', this.onClickHide.bind(this));
    
    this.formObject = new CommentForm(container, this.subCommentsContainer, this);
  },
  
  afterSave: function()
  {
    this.hide(true);
  }
})

var CommentForm = Class.create({  
  initialize: function(container, subCommentsContainer, link)
  {
    this.container = container;
    this.subCommentsContainer = subCommentsContainer;
    this.linkObject = link;
    
    this.form = container.select('form')[0];
    this.submit = container.select('.submit_comment')[0];
    Event.observe(this.submit, 'click', this.onClickSubmit.bind(this));
    
    this.setupClears();
  },
  
  setupClears: function()
  {
    this.cleared = {};
    this.form.select('.comment_field').each(
      (function(field) {
        if (field.getValue() == CommentDefaults[field.name])
        {
          field.addClassName('unaltered');
          Event.observe(field, 'focus', this.onFocusClear.bind(this));
        }
      }).bind(this)
    );
  },
  
  onFocusClear: function(event)
  {
    var field = Event.element(event);
    
    if (this.cleared[field.name]) return;
    
    field.removeClassName('unaltered');
    field.setValue("");
    
    this.cleared[field.name] = true;
  },

  reset: function()
  {
    this.form.select('p.error').each(function(error){error.hide();});
    this.form.select('.comment_field').each(function(field) {
      field.setValue(CommentDefaults[field.name]);
    });
    this.submit.enable();
    this.setupClears();
  },
  
  onClickSubmit: function(event)
  {
    this.submit.disable();
    this.form.request({
      onSuccess: this.doLoadChild.bind(this),
      onFailure: function() {
        alert("Something went wrong! I couldn't save your comment.");
      }
    });
    
    Event.stop(event);
  },
  
  // WARNING: This method blows! I know it!
  doLoadChild: function(xhr)
  {
    // Stick the responseText in a temp element first so we don't 
    // reinstantiate all the objects living in the parent element.
    var temp = new Element('div');
    temp.innerHTML = xhr.responseText;
    var newContainer = temp.firstDescendant();
    
    var error = (newContainer.select('form').length > 0);
    var containerParent = this.container.parentNode;
    containerParent.removeChild(this.container);
    
    if (error)
    {
      // ruh roh!
      if (this.linkObject)
      {
        this.linkObject.attachFormEvents(newContainer);
      }
      else
      {
        new CommentForm(newContainer, this.subCommentsContainer);
      }
      containerParent.appendChild(newContainer);
    }
    else
    {
      var noComments = $("no_comments_yet");
      if (noComments)
      {
        noComments.parentNode.removeChild(noComments);
      }
      
      // Append the new sub-comment followed by the container
      this.subCommentsContainer.appendChild(newContainer);
      containerParent.appendChild(this.container);
      
      // Initialize new sub-comment
      CommentManager.createAll(newContainer);
      
      new Effect.Highlight(newContainer, { duration: 1 });
      
      this.reset();
      
      if (this.linkObject) this.linkObject.afterSave();
    }
  }
});

if (CommentDefaults == null)
{
  var CommentDefaults = {};
}