
var MooBox = new Class({
  Implements : [Options, Events, Chain],

  options : {
    selectors   : 'a[rel=moobox]',
    path_moobox : 'js/',
    skin        : 'default',
    initWidth   : 200,
    initHeight  : 200,
    relativeTo  : $(document.body),
    multibox    : false,
    animate     : true
  },

  initialize : function(options){
    this.setOptions(options);
    this.css();
    this.links = $$(this.options.selectors);
    this.id = this.setId();
    this.attach();
  },

  css : function(){
    if($('MooBoxStyle')) return;

    var url = $$('script[src$=moobox.js]')[0];
    if(!url) return;
    url = url.get('src');
    url = url.substr(0, url.length -3);
    
    new Asset.css(url + '/moobox.css', {id: 'MooBoxStyle'});
  },

  attach : function(){
    this.links.each(function(link){
      if(link.retrieve('moobox')) return;

      var title = link.get('title') || link.get('alt');
      if(title){
        link.store('title', title);
        link.removeProperty('title');
      }
      link.addEvent('click', this.show.pass(link, this));
      link.store('moobox', this);
    }, this);
  },

  show : function(el){
    if(this.options.multibox) this.id = this.setId();
    this.setContent(el.get('href'), el.retrieve('title'), el);
    return false;
  },

  close : function(id){
    if($(id))
      $(id).destroy();
  },

  addContent : function(content, title){
    this.setHTML();
    this.boxContent.empty();
    if($type(content) == 'string'){
      var element = new Element('div', {'class':'MooBoxContent', 'html':content});
    }
    else if($type(content) == 'element'){
      var element = content;
    }

    this.boxContent.adopt(element);
    if($defined(title)) this.addTitle(title);
    this.addButton('close', 'CLOSE');
    this.showBox.delay(200, this, {width:element.getSize().x, height:element.getSize().y});
  },

  setContent : function(link, title, element){
    this.setHTML();
    var self = this;
    var data = $H({width:600, height:400});
    var d    = (element.get('data')) ? element.get('data').parseQueryString() : {};
    data.extend(d);
    data = data.getClean();

    // Reviso que sea una imagen lo que se va a mostrar
    if(this.isImage(link)){
      this.boxContent.empty();
      new Asset.image(link, {
        onload : function(){
          this.inject(self.boxContent);
          this.setStyle('opacity', 0);

          self.addTitle(title);
          self.addButton('close', 'CLOSE');
          self.showBox.delay(200, self, this);
        }
      });
    }
    //  Si es un flash
    else if(this.isFlash(link)){
      var obj = new Swiff(link, {
        width: data.width.toInt(),
        height: data.height.toInt(),
        params: {wmode: 'opaque', bgcolor: '#000000'}
      }).inject(this.boxContent);

      this.addTitle(title);
      this.addButton('close', 'CLOSE');
      this.showBox.delay(200, this, {width:data.width.toInt(), height:data.height.toInt()});
    }
    //  Para URLs muestro un iframe
    else{
      var obj = new Element('iframe', {
        'src' : link,
        'width' : data.width.toInt(),
        'height': data.height.toInt(),
        'frameborder' : 0,
        'scrolling' : 'no'
      }).inject(this.boxContent);

      this.addTitle(title);
      this.addButton('close', 'CLOSE');
      this.showBox.delay(200, this, {width:data.width.toInt(), height:data.height.toInt()});
    }
  },

  showBox : function(el){
    this.addFooter(new Element('div', {'class':'clear'}));
    this.setSize(this.boxContent, el.width, el.height);
    return this.animSizes(el);

  },

  addButton : function(type, text, event){
    if($type(event) != 'function'){
      event = function(){ return true; }
    }
    
    switch(type){
      case 'close':
        if(this.boxFooter.getElement('input[name=close]')) return;
        var btn = new Element('input', {'type':'button', 'name':'close', 'value':text, 'class':'inputbutton-close'});
        btn.addEvent('click', this.close.pass(this.id, this));
        break;

      case 'custom':
        var name = text.toLowerCase().replace(/ /g, '_');
        if(this.boxFooter.getElement('input[name='+name+']')) return;
        var btn = new Element('input', {'type':'button', 'name':name, 'value':text, 'class':'inputbutton-close'});
        btn.addEvent('click', event.pass([this.id, this], this));
        break;
    }

    if($defined(btn))
      this.addFooter(new Element('span').adopt(btn));
  },

  setHTML : function(){
    if($(this.id)) return this.setSizes();

    this.boxBody = new Element('div', {'id':this.id, 'class':'MooBoxBody'}).inject(document.body);
    if(this.options.animate === false) this.boxBody.fade('hide');

    // Row top
    this.boxRowTop  = new Element('div', {'class':'MooBoxRowTop'}).inject(this.boxBody);
    this.boxRowTopL = new Element('div', {'class':'mb-left'}).inject(this.boxRowTop);
    this.boxRowTopM = new Element('div', {'class':'mb-middle'}).inject(this.boxRowTop);
    this.boxRowTopR = new Element('div', {'class':'mb-right'}).inject(this.boxRowTop);
    this.clearDiv().inject(this.boxBody);

    // Row middle
    this.boxRowMid  = new Element('div', {'class':'MooBoxRowMid'}).inject(this.boxBody);
    this.boxRowMidL = new Element('div', {'class':'mb-left'}).inject(this.boxRowMid);
    this.boxRowMidM = new Element('div', {'class':'mb-middle'}).inject(this.boxRowMid);
    this.boxRowMidR = new Element('div', {'class':'mb-right'}).inject(this.boxRowMid);
    this.clearDiv().inject(this.boxBody);

    // Row bottom
    this.boxRowBot  = new Element('div', {'class':'MooBoxRowBot'}).inject(this.boxBody);
    this.boxRowBotL = new Element('div', {'class':'mb-left'}).inject(this.boxRowBot);
    this.boxRowBotM = new Element('div', {'class':'mb-middle'}).inject(this.boxRowBot);
    this.boxRowBotR = new Element('div', {'class':'mb-right'}).inject(this.boxRowBot);
    this.clearDiv().inject(this.boxBody);

    this.boxTitle   = new Element('div', {'class':'mb-title'}).inject(this.boxRowMidM);
    this.boxContent = new Element('div', {'class':'mb-content'}).inject(this.boxRowMidM);
    this.boxFooter  = new Element('div', {'class':'mb-footer'}).inject(this.boxRowMidM);
    this.setSize(this.boxContent, this.options.initWidth, this.options.initHeight);

//     this.boxBody.setStyle('visibility', 'hidden');

    this.setSizes();
  },

  setSizes : function(){
    var dim = this.boxContent.getDimensions();

    // Row Top
    this.setSize(this.boxRowTop, this.boxRowTopL.getSize().x + dim.width + this.boxRowTopR.getSize().x);
    this.setSize(this.boxRowTopM, dim.width);

    // Row Bot
    this.setSize(this.boxRowBot, this.boxRowBotL.getSize().x + dim.width + this.boxRowBotR.getSize().x);
    this.setSize(this.boxRowBotM, dim.width);

    // Row Mid
    var midHeight = dim.height + this.boxTitle.getSize().y + this.boxFooter.getSize().y;
    this.setSize(this.boxRowMid, this.boxRowMidL.getSize().x + dim.width + this.boxRowMidR.getSize().x, midHeight);
    this.setSize(this.boxRowMidL, false, midHeight);
    this.setSize(this.boxRowMidM, dim.width, midHeight);
    this.setSize(this.boxRowMidR, false, midHeight);

    this.boxBody.position({relativeTo:this.options.relativeTo});

  },

  animSizes : function(el){

    if(this.options.animate === false) return this._showBox(el);

    var dim    = this.boxContent.getDimensions();
    var chains = [];

    chains.push(function(){
      var totalWidth  = this.boxRowMidL.getSize().x + dim.width + this.boxRowMidR.getSize().x;
      var totalHeight = this.boxRowTop.getSize().y + this.boxRowMid.getSize().y + this.boxRowBot.getSize().y;

      new Fx.Elements(
        [this.boxRowTop, this.boxRowTopM, this.boxRowBot, this.boxRowBotM, this.boxRowMid, this.boxRowMidM, this.boxBody], {
          onComplete : this.callChain.bind(this)
        }
      ).start({
        '0' : {'width' : this.boxRowTopL.getSize().x + dim.width + this.boxRowTopR.getSize().x},
        '1' : {'width' : dim.width},
        '2' : {'width' : this.boxRowBotL.getSize().x + dim.width + this.boxRowBotR.getSize().x},
        '3' : {'width' : dim.width},
        '4' : {'width' : this.boxRowMidL.getSize().x + dim.width + this.boxRowMidR.getSize().x},
        '5' : {'width' : dim.width},
        '6' : {'left'  : this.calculatePositions(totalWidth, totalHeight).left}
      })
    }.bind(this));

    chains.push(function(){
      var midHeight   = dim.height + this.boxTitle.getSize().y + this.boxFooter.getSize().y;
      var totalWidth  = this.boxRowMidL.getSize().x + dim.width + this.boxRowMidR.getSize().x;
      var totalHeight = this.boxRowTop.getSize().y + midHeight + this.boxRowBot.getSize().y;

      new Fx.Elements(
        [this.boxRowMid, this.boxRowMidL, this.boxRowMidM, this.boxRowMidR, this.boxBody], {
          onComplete : this.callChain.bind(this)
        }
      ).start({
        '0' : {'height' : midHeight},
        '1' : {'height' : midHeight},
        '2' : {'height' : midHeight},
        '3' : {'height' : midHeight},
        '4' : {'top'    : this.calculatePositions(totalWidth, totalHeight).top}
      })
    }.bind(this));

    if($type(el) == 'element'){
      chains.push(function(){
        new Fx.Tween(el, { onComplete : this.callChain.bind(this) }).start('opacity', 1);
      }.bind(this));
    }

    this.chain(chains);
    this.callChain();

    return true;
  },

  _showBox : function(el){
    var dim         = this.boxContent.getDimensions();
    var totalWidth  = this.boxRowMidL.getSize().x + dim.width + this.boxRowMidR.getSize().x;
    var totalHeight = this.boxRowTop.getSize().y + this.boxRowMid.getSize().y + this.boxRowBot.getSize().y;

    this.boxRowTop.setStyles({'width' : this.boxRowTopL.getSize().x + dim.width + this.boxRowTopR.getSize().x});
    this.boxRowTopM.setStyles({'width' : dim.width});
    this.boxRowBot.setStyles({'width' : this.boxRowBotL.getSize().x + dim.width + this.boxRowBotR.getSize().x});
    this.boxRowBotM.setStyles({'width' : dim.width});
    this.boxRowMid.setStyles({'width' : this.boxRowMidL.getSize().x + dim.width + this.boxRowMidR.getSize().x});
    this.boxRowMidM.setStyles({'width' : dim.width});
    this.boxBody.setStyles({'left'  : this.calculatePositions(totalWidth, totalHeight).left});

    var midHeight = dim.height + this.boxTitle.getSize().y + this.boxFooter.getSize().y;
    totalWidth    = this.boxRowMidL.getSize().x + dim.width + this.boxRowMidR.getSize().x;
    totalHeight   = this.boxRowTop.getSize().y + midHeight + this.boxRowBot.getSize().y;

    this.boxRowMid.setStyles({'height' : midHeight});
    this.boxRowMidL.setStyles({'height' : midHeight});
    this.boxRowMidM.setStyles({'height' : midHeight});
    this.boxRowMidR.setStyles({'height' : midHeight});
    this.boxBody.setStyles({'top'    : this.calculatePositions(totalWidth, totalHeight).top});


    if($type(el) == 'element'){
      new Fx.Tween(el).start('opacity', 1);
    }
    this.boxBody.fade('show');

    return true;

  },

  calculatePositions : function(w, h){
    var el = new Element('div', {
      'styles': {
        'width'  : w,
        'height' : h,
        'overflow' : 'hidden'
    }}).inject(document.body);
    var pos = el.position({relativeTo:this.options.relativeTo, returnPos:true});
    el.destroy();

    if(pos.top < 0) pos.top = 1;

    return pos;
  },

  addTitle : function(title){
    if(!$defined(title) || title == ''){
      this.boxTitle.hide();
      return;
    }

    this.boxTitle.empty();
    this.boxTitle.adopt(new Element('span', {'html':title}));
    this.boxTitle.show();
  },

  addFooter : function(element){
    if(!$defined(element)){
      this.boxFooter.hide();
      return;
    }

    element.inject(this.boxFooter);
    this.boxFooter.show();
  },

  setSize : function(el, w, h){
    if(!el || !$defined(el)) return;
    w = (!$defined(w) || !w) ? el.getDimensions().width : w;
    h = (!$defined(h) || !h) ? el.getDimensions().height : h;

//     console.info('El: %o, Width: %o, Height: %o', el, w, h);

    el.setStyles({
      'width' : w,
      'height': h
    });
  },

  setId : function(){
    return 'MooBox_' + $time();
  },

  clearDiv : function(){
    return new Element('div', {'styles' : { 'clear':'both' }});
  },

  isImage : function(str){
    var exts = ['jpg', 'jpeg', 'png', 'gif'];
    return this.chkLink(str, exts);
  },

  isFlash : function(str){
    var exts = ['swf'];
    return this.chkLink(str, exts);
  },

  isVideo : function(str){
    var exts = ['flv'];
    return this.chkLink(str, exts);
  },

  isSound : function(str){
    var exts = ['mp3'];
    return this.chkLink(str, exts);
  },

  chkLink : function(lnk, exts){
    if(!$defined(exts) || !$defined(lnk)) return false;
    if(!['string', 'array'].contains($type(exts))) return false;
    if($type(exts) == 'string') exts = [exts];
    var ext = lnk.split('.').getLast().toLowerCase();
    return exts.contains(ext);
  }
});

window.addEvent('domready', function(){
  new MooBox({relativeTo : document.body});
})