var RevisionBar = Class.create({
  initialize: function(pageId, revisions, editable) {
    this.pageId = pageId;
    this.revisions = revisions.reverse();
    this.element = new Element("div", {id: 'revision_bar'});
    this.editable = editable;
    $(document.body).insert(this.element);
    fixIEOverlay(this.element);
    $(document.body).setStyle({marginBottom: '30px'});
    this.revisions.each(function(r) {r.date = parse_date(r.date)});
    this.addCount();
    this.addButtons();
    this.layoutRevisions();
  },
  addCount: function() {
    this.count = new Element("div", {id: 'revision_count'});
    this.element.insert(this.count);
    this.count.insert(this.revisions.length + " Revisions:");
    this.count.insert(new Element("img", {src: '/images/revision_gradient.png'}));
  },
  addButtons: function() {
    this.button_bar = new Element("div", {id: 'revision_buttons'});
    this.element.insert(this.button_bar);
    var tr = new Element('tr')
    this.button_bar.insert(new Element('table').insert(new Element('tbody').insert(tr)));
    tr.insert(new Element('td').update('Today'));
    this.images = {
      publish: "/images/button_publish.png",
      disabledPublish: "/images/button_disabled_publish.png",
      approve: "/images/button_approve.png",
      disabledApprove: "/images/button_disabled_approve.png"
    }
    if(this.editable) {
      tr.insert(new Element('td').update('<img alt="Edit" src="/images/button_edit.png" style="width: 50px; height: 26px; cursor: pointer" />').observe('click', function() { PageEditor.open(); }));
      this.publishButton = new Element('img', {alt: "Publish", src: this.images.disabledPublish, style: "width: 85px; height: 26px;"});
      tr.insert(new Element('td').insert(this.publishButton));
      tr.insert(new Element('td').update('<img alt="Edit" src="/images/button_settings.png" style="width: 77px; height: 26px; cursor: pointer" />').observe('click', function() { $('edit_page_dialog').open(); }));
    }
    this.offset = this.button_bar.getWidth();
  },
  layoutRevisions: function() {
    var current_revision = this.revisions.detect(function(r) {return r.draft == false});
    if (current_revision)
      current_revision.current = true;
    var latest = this.revisions.detect(function(r) {return r.pending_approval == true && r.draft == true && ((current_revision && current_revision.version || 0) < r.version)}) || this.revisions.first();
    var min = 18;
    var max = 50;
    
    var previous_time = null;
    var previous_position = 0;
    this.revisions.each(function(rev) {
      if (previous_time) {
        var x = (previous_time - rev.date) / 1000 / 60 / 60 / 24;
        var y = min + (max - min) * (2/(1 + Math.pow(Math.E, -0.1*x)) - 1);
        rev.x = previous_position + Math.ceil(y);
      } else {
        // HACK: The image is wider than the circle...
        rev.x = -10;
      }
      previous_position = rev.x
      previous_time = rev.date;
      var revision = new Revision(rev, this);
      if ((this.editable && latest == rev) || (!this.editable && rev.current))
        this.activate(revision);
    }.bind(this));
  },
  activate: function(revision) {
    if (this.current) this.current.element.removeClassName('current');
    this.current = revision;
    this.current.element.addClassName('current');
    var currentRevision = this.revisions.detect(function(r) {return r.draft == false});
    if (this.publishButton && revision.revision.draft && (revision.revision.publishable || revision.revision.approval_requestable) && (currentRevision && currentRevision.version < revision.revision.version || !currentRevision)) {
      this.publishButton.src = revision.revision.pending_approval ? this.images.approve : this.images.publish;
      this.activateButton(this.publishButton);
      this.publishButton.observe('click', this.publish.bind(this));
    } else {
      this.publishButton.src = revision.revision.pending_approval ? this.images.approve : this.images.publish;
      this.deactiveButton(this.publishButton);
      this.publishButton.stopObserving('click');
    }
  },
  publish: function() {
    if(this.current)
      this.current.publishRevision();
  },
  activateButton: function(button) {
    button.src = button.src.replace('_disabled', '');
    button.setStyle({cursor: 'pointer'});
  },
  deactiveButton: function(button) {
    if(!button.src.include('disabled'))
      button.src = button.src.replace('button', 'button_disabled')
    button.setStyle({cursor: 'default'})
  }
});

var Revision = Class.create({
  initialize: function(revision, bar) {
    this.revision = revision;
    this.bar = bar
    this.element = new Element("div", {className: 'revision'}).setStyle({right: (revision.x + this.bar.offset) + 'px'});
    if (revision.draft) this.element.addClassName('draft');
    this.bar.element.insert(this.element);
    this.buildPopup();
    this.element.observe('mouseover', this.showPopup.bind(this));
    this.element.observe('mouseout', this.hidePopup.bind(this));
    this.popup.observe('mouseover', this.popup.show.bind(this.popup));
    this.popup.observe('mouseout', this.hidePopup.bind(this));
    this.element.observe('click', this.showRevision.bind(this));
    this.popup.observe('click', this.showRevision.bind(this));
  },
  buildPopup: function() {
    this.popup = new Element('div', {className: 'revision-popup-container'});
    var border = createBorder('revision_popup');
    this.table = border[0];
    this.popup.insert(border[0]);
    this.popup.setStyle({right: (this.revision.x + this.bar.offset - 36) + "px"});
    this.popupContent = new Element('div');
    border[1].insert(this.popupContent);
    this.arrow = new Element('img', {className: 'arrow', src: '/images/revision_popup_arrow.png'})
    this.popup.insert(this.arrow);
    this.popup.hide();
    this.popupContent.insert(new Element('div').update("Version: " + this.revision.version + (this.revision.draft ? " (Draft)" : "")));
    this.popupContent.insert(new Element('div').update("Author: " + this.revision.author));
    this.popupContent.insert(new Element('div').update("Date: " + this.revision.date.strftime("%m/%d/%Y %I:%M %p")));
    this.bar.element.insert(this.popup);
  },
  showRevision: function() {
    new Ajax.Updater('page_content', '/' + this.bar.pageId + '/versions/' + this.revision.version, {method: 'get', onComplete: setupMailtoLinks});
    this.bar.activate(this);
  },
  publishRevision: function() {
    if (this.revision.publishable) {
      new Ajax.Updater('page_content', '/' + this.bar.pageId + '/publish/' + this.revision.version, {method: 'put', parameters: {authenticity_token: window._token}});
      this.revision.draft = false;
      this.element.remove();
      this.initialize(this.revision, this.bar);
      this.bar.activate(this);
    } else if (this.revision.approval_requestable) {
      new Ajax.Updater('page_content', '/' + this.bar.pageId + '/request_approval/' + this.revision.version, {method: 'put', parameters: {authenticity_token: window._token}});
      this.revision.pending_approval = true;
      this.bar.activate(this);
    } 
  },
  showPopup: function() {
    this.popup.show();
    if (Prototype.Browser.IE) return;
    this.popupContent.hide();
    this.table.setStyle({opacity: 0});
    this.arrow.setStyle({opacity: 0});
    new Fx.Style(this.arrow, 'opacity', {duration: 150}).custom(0, 1);
    new Fx.Styles(this.table, {duration: 150, onComplete: function() {
      this.popupContent.setStyle({opacity: 0});
      this.popupContent.show();
      new Fx.Style(this.popupContent, 'opacity', {duration: 100}).custom(0, 1);
    }.bind(this)}).custom({height: [10, 60], width: [10, 220], opacity: [0, 1]});
  },
  hidePopup: function() {
    this.popup.hide();
  }
})

function parse_date(v) {
  return (typeof v == "string" && (k=v.match(/([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(Z|-\d{2}:\d{2})$/))) ? new Date(Date.UTC(k[1],k[2]-1,k[3],k[4],k[5],k[6])) : v;
}
