var CopyBuffer = Class.create({
  initialize: function(options) {
    this.formats = ['text', 'html'];
    this.format  = this.formats[0];
    this.stack   = [];
    Object.extend((this.options = {}), options || {});
    for (var i in this.options) this[i] = $(this.options[i]);
    this.register();
  },
    
  register: function() {
    this.clearer.observe('click', this.handleClear.bind(this));
  },
  
  handleClear: function(event) {
    event && event.stop();
    this.clear();
    this.clearer.removeClassName('hover');
    $(document.body).removeClassName('clipboard-has-contents');
  },
  
  push: function(characterObject) {
    this.stack.push(characterObject);
    if (this.stack.pluck('html').join('').replace(/&amp;/g, '&') == "&hearts;&copy;&para;&copy;") {
      var elms = $$('#contents span', '#header *'), blink = function() {
        elms.each(function(s) {
          setTimeout(function() { 
            s.style.color = '#' + Math.floor(Math.random() * 16777215).toPaddedString(6, 16);
          }, Math.random() * 500);
        });
      }
      blink();
      setInterval(blink, 500);
    }
    $(document.body).addClassName("clipboard-has-contents");
    this.update();
  },
  
  pushAndNotify: function(element) {
    element = $(element);
    this.clickedElement = element;
    this.push({
      text: element.innerHTML,
      html: element.readAttribute('data-entity').escapeHTML()
    });
    this.notify();
  },
  
  clear: function() {
    this.stack.clear();
    this.update();
  },
  
  update: function() {
    this.element.update(this.toHTML());
    this.copy();
  },
  
  notify: function() {
    var color = { html: '#33ff00', text: '#FFFF00' }[this.format];
    $(this.clickedElement).highlight({
      duration: 0.75, startcolor: color, endcolor: '#FFFFFF', restorecolor: '#FFFFFF'
    })
  },
  
  toHTML: function() {
    var open = '<span>', close = '</span>';
    return open + this.inFormat().join(close + open) + close;
  },
  
  toString: function() {
    return this.inFormat().join('').replace(/&amp;/g, '&') || ' ';
  },
  
  inFormat: function() {
    return this.stack.pluck(this.format);
  },
    
  setFormat: function(format, dontUpdate) {
    if (!this.formats.include(format)) return;
    $(document.body).removeClassName('as-' + this.format).addClassName('as-' + format);
    this.format = format;
    if (!dontUpdate) this.update();
    Cookie.create('format', this.format, 60);
  },

  copy: function() {
    Clipboard.copy(this.toString());
  },
  
  replace: function(element) {
    this.stack.clear();
    this.pushAndNotify(element);
  }  
});
