/** Never show the backdrop */
ta.overlays.BACKDROP_NEVER  = 0;
/** Always show the backdrop */
ta.overlays.BACKDROP_ALWAYS = 1;

/**
 * Common base class for all floating overlay elements. A overlay is an element that appears on the page
 * above all other elements and is absolutely positioned over the document. This class will
 * automatically place an iframe behind the overlay to block select element in IE6.
 * @class
 *
 * @option {boolean} [showCloseButton=false] Whether or not to show the close button
 * @option {String}  [style=typeO] Class name on container div.
 * @option {boolean} [backdrop=ta.layers.BACKDROP_NEVER] Should be one of ta.layers.BACKDROP_*
 */
ta.overlays.Overlay = new Class({
  options: {
    requestData:      null,
    showCloseButton:  false,
    style:            'typeO',
    backdrop:         ta.overlays.BACKDROP_NEVER,
    isChild:          false,
    remoteContent:    null
  },
  
  /**
   * @param {Object} options Options, see below.
   */
  initialize: function(options, elmt) {
    this.setOptions(options);
    this.source = $(elmt);
    // state flags
    this.visible    = false;
    this.backdropOn = false;
    
    // bind event handlers
    this.showHandler = this.show.bindWithEvent(this);
    this.hideHandler = this.hide.bindWithEvent(this);
    
    // setup container
    this.container = new Element('div', {
      styles: {
        position: 'absolute',
        left: '-999em',
        top: '-999em',
        fontSize: '.75em',
        zIndex: '1001'
      },
      'class': this.options.style + " overlay"
    });
    this.container.overlay = this;
    this.inner = new Element('div', {
      'class': 'inner'
    }).injectInside(this.container);
    
    if (this.options.showCloseButton) {
      this.closeBtn = new Element('div', {
        styles: {
          position: 'absolute',
          fontSize: '92.5%',
          cursor: 'pointer'
        },
        'class': 'close'
      }).inject(this.container);
      this.inner.addClass('withClose');
    }
    
    // IE6 requires an IFrame shim
    if (window.ie6) {
      this.shim = new Element('iframe', {
        styles: {
          position: 'absolute',
          left: '-999em',
          top: '-999em',
          border: 'none'
        }
      });
    }
    
    if (this.options.content) {
      this.inner.setHTML(this.options.content);
    }
    else if (this.options.remoteContent) {
      this.loadRemoteContent(this.options.remoteContent);
    }

    this.container.addEvent('trash', this.destroy.bind(this));
  },

  destroy: function(){
    this.container.overlay = null;
  },
  
  /**
   * Positions the container.
   */
  position: function() {
  	this.positionShim();
  },
  
  /**
   * Positions the IFrame shim if necessary.
   */
  positionShim: function() {
  	if (!this.shim) return;
    // a small delay is needed in case the popup styles change its size
    (function(){
      this.shim.injectBefore(this.container);
      var c = this.container.getCoordinates();
      this.shim.setStyles({
        left: c.left,
        top: c.top,
        width: c.width,
        height: c.height,
        zIndex: this.container.getStyle('z-index') - 1
      });
    }).delay(10, this);
  },
  
  /**
   * Adds the container to the DOM and positions it.
   * @param {Event} evnt The event
   */
  show: function(evnt) {
    if (this.visible) return;
    if (evnt) new Event(evnt).preventDefault();
    
    // it is possible for an overlay to spawn multiple child overlays, so find other overlays and
    // remove them if they aren't the parent overlay
    // or if they have not been flagged as permanent (like the dhtml popups) - see bug 40975.
    $$('.overlay').each(function(other){
      if (other.overlay == this) return;
      if (this.parentOverlay && other.overlay == this.parentOverlay) return;
      if (other.overlay instanceof ta.overlays.PermanentOverlay) return;
      other.overlay.hide(evnt);
    }, this);
    
    $(document.body).adopt(this.container);
    this.position();
    this.positionShim();
    if (this.options.backdrop == ta.overlays.BACKDROP_ALWAYS) this.enableBackdrop();
    this.visible = true;
    this.fireEvent('onShow', this);
    return this;
  },
  
  /**
   * Removes the container from the DOM.
   * @param {Event} evnt The event
   */
  hide: function(evnt) {
    if (window.flyout) window.flyout.hide();
    if (this.backdropOn) this.disableBackdrop();
    if (!this.container.inDocument()) return this;
    if (this.shim) {
      this.shim.setStyles({
        left: '-999em',
        top: '-999em'
      });
      if (this.shim.inDocument()) this.shim.remove();
    }
    this.container.setStyles({
      left: '-999em',
      top: '-999em'
    }).remove();
    this.visible = false;
    this.fireEvent('onHide',!evnt);
    return this;
  },
  
  /**
   * Configures the backdrop.
   */
  configureBackdrop: function() {
    this.backdrop = new Element('div');
    this.backdrop.setStyles({
      position: 'absolute',
      left: 0,
      top: 0,
      width: window.getScrollWidth(),
      height: window.getScrollHeight(),
      backgroundColor: '#000',
      zIndex: this.options.isChild ? '10000' : '9997'
    }).setOpacity(0.6);
  },
  
  /**
   * update backdrop on show
   */
  updateBackdrop: function() {
    this.backdrop.setStyles({
      width: window.getScrollWidth(),
      height: window.getScrollHeight()
    });
  },
  
  /**
   * Adds the opacity backdrop behind this layer.
   */
  enableBackdrop: function() {
    if (this.backdropOn) return;
    if (!this.backdrop) this.configureBackdrop();
    if(window.ie6)
    {
      var container = this.container;
      $$('select').each(function(elem){
        if(!container.hasChild(elem))
        {
          elem.setStyle('visibility', 'hidden');
        }
        else
        {
          elem.setStyle('visibility', 'visible');
        }
      });
    }
    ta.store('overlays.current', this);
    this.updateBackdrop();
    if(this.container.inDocument()) this.backdrop.injectBefore(this.container);
    else this.backdrop.injectBefore(document.body);
    this.backdropOn = true;
    this.container.setStyle('z-index', this.options.isChild? '10002' : '9998');
  },
  
  /**
   * Removes the opacity backdrop from behind this layer.
   */
  disableBackdrop: function() {
    if (!this.backdropOn) return;
    this.backdrop.remove();
    if(ta.retrieve('overlays.current') == this)
    {
      ta.remove('overlays.current');
      if(window.ie6)
      {
        $$('select').setStyle('visibility', 'visible');
      }
    }
    else
    {
      if(window.ie6 && ta.retrieve('overlays.current') && !ta.retrieve('overlays.current').backdropOn)
      {
        $$('select').setStyle('visibility', 'visible');
      }
    }
    this.backdropOn = false;
    this.container.setStyle('z-index', '1001');
  },
  
  /**
   * Request remote content.
   */
  loadRemoteContent: function(uri, bHideSpinner) {
    if(!bHideSpinner)
    {
        new Asset.image(CDNHOST + '/img2/generic/site/loop.gif', {
          onload: this.position.bind(this),
          'class': 'anim_loop'
        }).injectInside(this.inner);
    }
    new Ajax(ta.util.URL.parse(uri), {
      data: this.options.requestData,
      onSuccess: this.loadRemoteSuccess.bind(this),
      onFailure: this.loadRemoteFailure.bind(this),
      evalScripts: true
    }).request();
    return this;
  },
  
  /**
   * Called when remote content is successfully loaded.
   * @param {String} txt The remote content
   */
  loadRemoteSuccess: function(txt) {
    this.cachedWidth = null;
  	this.inner.setHTML(txt);
    this.position();
    if(typeof behavior != 'undefined' && behavior && behavior.apply)
    {
      behavior.apply(this.inner);
    }
    this.fireEvent('onLoad', this);
    this.cachedWidth = this.container.getSize().size.x;
    return this;
  },
  
  /**
   * Called when remote content fails to load.
   */
  loadRemoteFailure: function() {
    this.inner.setText(JS_Ajax_failed);
  }
});
ta.overlays.Overlay.implement(new Options, new Events);
