var Effect = Effect || undefined;

Panel = Class.create({
  initialize: function(options) {
    this.setOptions(options);
    this.selectshidden = false;
    this.isIE6 = (navigator.userAgent.indexOf('MSIE 6.0') != -1);
    this.buildElements();
  },
  buildElements: function() {
    this.buildPanel();
    this.buildOverlay();
    if(this.isIE6) this.buildIE6iframe();
    this.updateContent();
  },

  buildPanel: function() {
    this.panel_id = (this.options.panelId) ? this.options.panelId : 'panel_'+Math.floor(Math.abs(Math.random()*(2<<30))).toString(36);
    this.element = $(this.panel_id) || new Element('div',{id:this.panel_id}).hide();
    this.element.setStyle({
      position:((this.isIE6)? 'absolute' : 'fixed'),
      zIndex:9001
    });
    Element.insert(document.body,{top:this.element});
  },

  buildOverlay: function() {
    if(!this.options.displayOverlay) return;
    this.overlay = $(this.options.overlayId) || new Element('div',{id:this.options.overlayId}).hide();
    this.overlay.setStyle({
      backgroundColor:this.options.overlayColor,
      opacity:this.options.overlayOpacity,
      position:((this.isIE6)? 'absolute' : 'fixed'),
      width:'100%',
      height:'100%',
      zIndex:9000,
      left:0,
      top:0
    })
    if(this.isIE6) {
      this.overlay.setStyle({padding:$(document.body).getStyle('margin')})
    }
    $(document.body).insert({top:this.overlay});
  },

  buildIE6iframe: function() {
    this.iefix = new Element('iframe').setStyle({opacity:0,position:'absolute',zIndex:8999}).hide();
    $(document.body).insert(this.iefix);
  },

  updateContent: function(content) {
    if(this.options.url) {
      this.loadInfo();
    } else {
      var content = content || this.options.content;
      if(Object.isElement(content)) content.show();
      this.element.update().insert(content);
      this.element.className = this.options.panelClass;
    }
  },

  clickOut: function(event) {
    if(Event.element(event) == this.element || Event.element(event).descendantOf(this.element)) return;
    if(this.options.excludeFromClickOut) {
      var excluded_clicked = this.options.excludeFromClickOut.find(function(el) {
        if(!$(el)) return false;
        if(Event.element(event) == $(el) || Event.element(event).descendantOf($(el))) return true;
      })
      if(excluded_clicked) return;
    }
    Event.stopObserving(document,'mouseup',this.clickout);
    if(this.options.onClickOut) this.options.onClickOut(this);
    this.close();
  },

  open: function(){
    this.fixIE6();
    if(this.overlay) this.overlay.show();
    this.toggleSelects();
    this.showPanel();
    if (this.options.enableClickOut) {
      this.clickout = this.clickOut.bind(this);
      Event.observe(document,'mouseup',this.clickout);
    }
    if(this.options.onOpen) this.options.onOpen(this)
    return this;
  },

  close: function() {
    this.fixIE6();
    this.toggleSelects();
    if(this.overlay) this.overlay.hide()
    this.hidePanel();
    if(this.options.onClose) this.options.onClose(this)
  },

  toggleSelects: function(){
    if (!this.isIE6) return;
    if(this.options.displayOverlay) {
      $$('select').invoke('toggle');
      this.element.select('select').invoke('show');
    } else {
      this.iefix.clonePosition(this.element);
      this.iefix.toggle();
    }
  },

  fixIE6: function() {
    if(!this.isIE6 || !this.options.displayOverlay) return;
    if(!this.overlay.visible()) {
        this.scrollPos = document.viewport.getScrollOffsets();
        $$('body')[0].setStyle({height:'100%',overflow:'hidden'})
        $$('html')[0].setStyle({height:'100%',overflow:'hidden'});
    } else {
        $$('body')[0].setStyle({height:'',overflow:''})
        $$('html')[0].setStyle({height:'',overflow:''});
        window.scrollTo(this.scrollPos[0],this.scrollPos[1]);
    }
  },

  loadInfo: function(url) {
    if(this.options.showLoading) {
      this.element.update(this.options.loadingText)
      this.element.className = this.options.loadingClass;
    }
    this.showPanel();
    this.options.ajaxOptions = Object.extend({
      evalScripts:true,
      onComplete:function(){
        this.element.className = this.options.panelClass;
        this.showPanel();
        if(this.options.onLoadComplete) this.options.onLoadComplete(this)
      }.bind(this),
      onFailure: function() {
        this.close();
        throw("There was a problem loading the content.");
      }.bind(this)
    },this.options.ajaxOptions)
    setTimeout(function(){ //remove for production
      new Ajax.Updater(this.element ,url||this.options.url,this.options.ajaxOptions);
    }.bind(this),10) //remove for production
  },

  setPosition: function() {
    if(this.options.positionRelativeTo) {
      this.target = $(this.options.positionRelativeTo);
      var targetCorner = this.getCorner(this.target,this.options.hooks[0]);
      var panelCorner = this.getCorner(this.element,this.options.hooks[1]);

      var tp = this.target.cumulativeOffset();
      var xPos = tp.left + targetCorner.left - panelCorner.left + this.options.offsetX;
      var yPos = tp.top + targetCorner.top - panelCorner.top + this.options.offsetY;

      this.element.setStyle({position:this.options.position,left:xPos+'px', top:yPos+'px', margin:0});

    } else {
      var panelDimensions = this.element.getDimensions();
      var xPos = ((panelDimensions.width/2)*-1) + this.options.offsetX;
      var yPos = ((panelDimensions.height/2)*-1) + this.options.offsetY;

      if(this.isIE6 && !this.options.displayOverlay) {
        var scrollOffsets = document.viewport.getScrollOffsets()
        xPos += scrollOffsets.left;
        yPos += scrollOffsets.top;
      }
      this.element.setStyle({top:'50%', left:'50%', marginLeft:xPos+'px', marginTop:yPos+'px'});
    }

  },
  showPanel: function() {
    this.setPosition();
    if(!Object.isUndefined(Effect) && this.options.showEffect) {
      Effect[this.options.showEffect](this.element,this.options.showEffectOptions);
    } else {
      this.element.show();
    }
    this.addActions();
  },

  hidePanel: function() {
    if(!Object.isUndefined(Effect) && this.options.hideEffect) {
      Effect[this.options.hideEffect](this.element,this.options.hideEffectOptions);
    } else {
      this.element.hide();
    }
  },

  addActions: function(){
    this.element.select("a.panel_action").each(function(el){
      Event.observe(el,'click', function(event){
        this[el.rel](el.href);
        event.stop();
      }.bind(this))
    }.bind(this));
  },

  update: function(url) {
    this.loadInfo(url);
  },

  getCorner: function(target,corner) {
    var dimensions = $(target).getDimensions();
    var xPos =
      (corner.match(/R/i)) ? dimensions.width :
      (corner.match(/L/i)) ? 0 : dimensions.width/2;
    var yPos =
      (corner.match(/B/i)) ? dimensions.height :
      (corner.match(/T/i)) ? 0 : dimensions.height/2;
    return {left:xPos,top:yPos}
  },

  setOptions: function(options) {
    this.options = Object.extend({
      panelId:null,
      overlayId:'overlay',
      overlayOpacity:0.3,
      overlayColor:'#666666',
      displayOverlay:true,
      positionRelativeTo:null,
      position:'absolute',
      hooks:['C','C'],
      offsetX:0,
      offsetY:0,
      showEffect:null,
      showEffectOptions:{},
      hideEffect:null,
      hideEffectOptions:{},
      url:null,
      ajaxOptions:{},
      loadingText:'Loading...',
      content:null,
      panelClass:'panel',
      loadingClass:'panel_loading',
      showLoading:true,
      enableClickOut:false,
      excludeFromClickOut:null,
      onOpen:function(){},
      onClose:null,
      onLoadComplete:null
    }, (options || {}));
  }
});