var Swappable = new Class({
  initialize: function(containerElement, opts) {
    this.container = containerElement;
    this.reloadOrder();
    this.setupButtons();
    if (opts) {
      this.cookieOpts = opts.cookieOpts === undefined ? {duration:60} : opts.cookieOpts;
      this.persistent = opts.persistent === undefined ? true: opts.persistent;
      this.animate = opts.animate === undefined ? true : opts.animate;
    } else {
      this.cookieOpts = {duration: 60};
      this.persistent = true;
      this.animate = true;
    }
  },
  
  swap: function(source, where) {
    var place, node, parent;
    parent = source.getParent('.swapBox');
    if (where === 'up') {
      place = 'before';
      node = parent.getPrevious();
    } else {
      place = 'after';
      node = parent.getNext();
    }
    if(node) {
      if (this.animate) {
        parent.set('tween', {duration: '250'});
        node.set('tween', {duration: '260'});
        var that = this;
        node.get('tween').addEvent('complete', function(e) {
          node.get('tween').removeEvents();
          parent.dispose();
          parent.inject(node, place).fade('in');
          if (that.persistent) {
            that.saveOrder();
          }
          node.fade('in');
        });
        
        parent.tween('opacity', '0');
        node.tween('opacity', '0');
      } else {
        parent.dispose();
        parent.inject(node, place).fade('in');
        if (this.persistent) {
          this.saveOrder();
        }
      }
    }
  },
  
  deleteCookie: function() {
    Cookie.dispose(this.container.get('id')+'Order');
  },
  
  reloadOrder: function() {
    var cookieName, cookieValue;
    var order, children, ids;
    
    cookieName = this.container.get('id')+'Order';
    cookieValue = Cookie.read(cookieName);
    if (cookieValue === null) { return; }
    order = JSON.decode(cookieValue);
    
    children = this.container.getChildren();
    ids = this.makeIdHash(children);
    var exists = true;
    order.each(function(idName) {
      var tmp = ids[idName];
      if (!tmp) {
        exists = false;
      }
    });
    if (!exists) {
      this.deleteCookie();
      return;
    }
    
    children.dispose();
    var that = this;
    order.each(function(idName) {
      var node = ids[idName];
      node.inject(that.container);
    });
  },
  
  setupButtons: function() {
    var idName = this.container.get('id');
    var that = this;
    $$('#'+idName+' .swapUp').addEvent('click', function() {
      that.swap(this, 'up');
    });
    $$('#'+idName+' .swapDown').addEvent('click', function() {
      that.swap(this, 'down');
    });
  },
  
  makeIdHash: function(elms) {
    var h = {};
    elms.each(function(el) {
      h[el.get('id')] = el;
    });
    return h;
  },
  
  saveOrder: function() {
    var ch = this.container.getChildren();
    var order = []
    ch.each(function(el) {
      order.include(el.get('id'));
    });
    Cookie.write(this.container.get('id')+'Order', JSON.encode(order), this.cookieOpts);
  },
});