var Page = Class.create({
  initialize: function(url, page_number, wrapper, pagination_wrapper) {
    this.page_elements_count  = 0;
    this.total_elements_count = 0;
    this.page_count           = 1;

    this.url                  = url;
    this.page_number          = page_number;
    this.wrapper              = $(wrapper);
    this.pagination_wrapper   = $(pagination_wrapper);

    this.window_loaded        = new Date();
    this.last_mouse_move      = this.window_loaded.getTime();
    this.minutes_stagnant_for = 0;

    // Load the page on init
    this.update();
  },
  fetch: function() {
    var objects = $H();
    var page_options = { page: this.page_number };
    new Ajax.Request(this.url, {asynchronous:false, evalScripts:true,
                                parameters: page_options,
                                onSuccess:function (request) {
                                  objects = request.responseText.evalJSON();

                                  this.page_elements_count = objects.count;
                                  this.total_elements_count = objects.total_count;
                                  this.page_count = objects.page_count;
                                  this.page_number = objects.page_number;
                                }.bind(this)
                               });
    return objects;
  },
  paginate: function() {
    // Clear DOM wrapper element
    this.pagination_wrapper.update('');

    if (this.page_count > 10) this.page_count = 10; // truncate pagination more than 10 looks silly

    // Add a link element for each page
    (this.page_count).times(function(n) {
      var page_link = this.link(n + 1);
      this.pagination_wrapper.insert(page_link);
      // Make the link responsive
      Event.observe(page_link, 'click', function(e) {
        // Update the instantiated object
        this.page_number = e.element().innerHTML;
        // Update the page
        this.update();
      }.bind(this)); // bound to the instantiated object
    }.bind(this));   // bound to the instantiated object
  },
  link: function(number) {
    var class_name = (this.page_number == number ? 'current' : 'normal');
    var link = new Element('a', { href: 'javascript:void(0);', id: 'page_link_' + number }).update(number);
    var wrap = new Element('div', { id: 'page_link_wrapper_' + number, 'class': class_name }).update(link);

    return wrap;
  },
  update: function () {
    // Fetch new objects
    this.elements = this.fetch();

    // Clear DOM wrapper element
    this.wrapper.update('');

    // Add an element for each object
    this.elements.each(function(element) {
      this.insert(element.toHTML());
    }.bind(this.wrapper));

    // Handle Pagination
    this.paginate();
  },
  start_updating: function(refresh, decay) {
    // Start observing mouse movement
    Event.observe(document, 'mousemove', function(mousemove) {
      // Store the time of the most recent mouse movement
      var movement = new Date();
      this.last_mouse_move = movement.getTime();
    });

    // Check every n seconds to see how stagnant we are
    new PeriodicalExecuter(function(periodically_update_page) {
      // Get the current amount of minutes the mouse has been stagnant for
      var now = new Date();
      this.minutes_stagnant_for = (now.getTime() - this.last_mouse_move) / 60000;

      if (this.minutes_stagnant_for < decay && parseInt(this.page_number) == 1) {
        this.update();              // Usage is stagnant for less than 30 minutes update the page
      }
    }.bind(this), refresh);
  }
});

var BlogPage = Class.create(Page, {
  fetch: function($super) {
    objects = $super();
    if (Object.keys(objects).include('posts')) {
      return objects.posts.collect(function (element) { return Object.toBlogPost(element) });
    } else {
      return $A();
    }
  }
});

var CommentPage = Class.create(Page, {
  initialize: function($super, url, page_number, wrapper, pagination, page_wrapper, form_wrapper, register_signin) {
    this.form_wrapper = $(form_wrapper);
    this.page_wrapper = $(page_wrapper);
    if (this.form_wrapper != undefined) {
      this.form_error = this.form_wrapper.select('.error').first();
      this.form_text  = this.form_wrapper.select('textarea').first();
      this.default_text = 'Your comment';
      this.register_signin = $(register_signin);
      this.user_id = null;
    }
    $super(url, page_number, wrapper, pagination);
  },
  fetch: function($super) {
    objects = $super();
    if (Object.keys(objects).include('comments')) {
      return objects.comments.collect(function (element) { return Object.toComment(element) });
    } else {
      return $A();
    }
  },
  clear_comment_text: function() {
    if (this.form_text.innerHTML == this.default_text) this.form_text.update('');
  },
  register_or_signin: function() {
    if (this.user_id == null) {
      new Ajax.Updater(this.register_signin, '/dan_patrick/register_signin',
                       {asynchronous:false, evalScripts:true, onSuccess:this.register_signin.show() });
      this.page_wrapper.hide();
      return false;
    } else {
      this.page_wrapper.show();
      this.register_signin.hide();
      return true;
    }
  },
  submit_comment: function() {
    this.clear_comment_text();
    new Ajax.Request(this.form_wrapper.action,
                     {asynchronous:true, evalScripts:true,
                       onSuccess:function(request){
                         this.form_wrapper.reset();
                         this.update();
                        }.bind(this),
                       on401:function(request){
                          this.register_or_signin();
                        }.bind(this),
                       on400:function(request){
                         this.form_error.show();
                         this.form_error.update(request.responseText)
                       }.bind(this),
                     parameters:Form.serialize(this.form_wrapper)});
    return false;
  }
});

Object.extend(Object, {
  toBlogPost: function(object) {
    return new BlogPost(object.id, object.title, object.created_at, object.message, object.user_id, object.user_name, object.user_url);  
  },
  toComment: function(object) {
    return new Comment(object.id, object.created_at, object.comment_text, object.user_id, object.user_name, object.user_url);
  }
});

var Comment = Class.create();
Comment.prototype = {
  initialize: function(id, created_at, comment_text, user_id, user_name, user_url) {
    // Comment
    this.id           = parseInt(id);
    this.created_at   = created_at.stripScripts().stripTags();
    this.comment_text = comment_text.stripScripts().stripTags();

    // User Stuff, maybe better in it's own class?
    this.user_id      = parseInt(user_id);
    this.user_name    = user_name.stripScripts().stripTags();
    this.user_url   = user_url.stripScripts().stripTags();
  },
  user_link: function() {
    return new Element('a', { href: this.user_url, target: '_top' }).update(this.user_name);
  },
  toHTML: function() {
    var head = new Element('span', { 'class': 'created_at' }).update(this.created_at);
    var body = new Element('span', { 'class': 'message' }).update('&nbsp;|&nbsp;' + this.comment_text + '&nbsp;|&nbsp;');
    var foot = new Element('span', { 'class': 'user' }).update(this.user_link());
    var wrap = new Element('div', { id: 'comment_' + this.id, 'class': 'comment' });

    wrap.insert(head);
    wrap.insert(body);
    wrap.insert(foot);
    return wrap;
  }
}

var BlogPost = Class.create({
  initialize: function(id, title, created_at, message, user_id, user_name, user_url) {
    this.id         = parseInt(id);
    this.title      = title.stripScripts().stripTags();
    this.created_at = created_at.stripScripts().stripTags();
    this.message    = message.stripScripts();

    // User Stuff, maybe better in it's own class?
    this.user_id      = parseInt(user_id);
    this.user_name    = user_name.stripScripts().stripTags();
    this.user_url   = user_url.stripScripts().stripTags();
  },
  user_link: function() {
    return new Element('a', { href: this.user_url, target: '_top' }).update(this.user_name);
  },
  toHTML: function() {
    var title = new Element('h2').update(this.title);
    var subtitle = new Element('span', { 'class': 'created_at' }).update(this.created_at);
    var body = new Element('span', { 'class': 'message_wrapper' }).update('&nbsp;|&nbsp;' + this.message + '&nbsp;|&nbsp;');
    var foot = new Element('span', { 'class': 'user' }).update(this.user_link());
    var wrap = new Element('div', { id: 'blog_post_' + this.id, 'class': 'blog_post' });

    wrap.insert(title);
    wrap.insert(subtitle);
    wrap.insert(body);
    wrap.insert(foot);
    return wrap;
  }
});

function open_lightbox() {
  $('register').hide();
  $('signin').hide();
  $('lightbox').show();
}

function close_lightbox() {
  $('lightbox').hide();
  $('register').show();
  $('signin').show();
}