var Modal = new Class({
  Implements: [Events, Options],
  options: {
    speed: 500,
    maskOpacity: 0.8,
    maskColor: '#000000',
    width: 400,
    caption: 'Window title',
    height: 'auto',
    classPrefix: 'Modal',
    onHide: $empty,
    onShow: $empty,
    onStart: $empty
  },
  initialize: function(options) {
    this.setOptions(options);
    this.isShowing = false;
    this.mask = new Element('div', {
      'class':this.options.classPrefix+'Mask',
      'styles':{
        'position':'absolute',
        'top': 0,
        'left': 0,
        'opacity': 0,
        'z-index': 9999,
        'background-color':this.options.maskColor
      },
      'events': {
        'dblclick':this.hide.bindWithEvent(this)
      }
    });
    this.message = new Element('div',{
      'class':this.options.classPrefix+'Message',
      'styles':{
        'height':this.options.height
      }
    });
    this.title = new Element('div',{
      'class':this.options.classPrefix+'Title',
      'text': this.options.caption
    });
    this.close = new Element('div',{
      'class':this.options.classPrefix+'Close',
      'events':{
        'click':this.hide.bindWithEvent(this)
      }
    });

    this.pop = new Element('div', {
      'class':this.options.classPrefix+'Pop',
      'styles':{
        'position': 'absolute',
        'visibility': 'hidden',
        'width': this.options.width,
        'left':'50%',
        'z-index': 10000
      }
    }).adopt(this.title, this.message, this.close);

    this.fx = {
      mask: this.mask.effect('opacity', {duration: this.options.speed}),
      slide: this.pop.effect('top',{duration:this.options.speed})
    };
    window.addEvents({
      'resize': this.update.bindWithEvent(this),
      'scroll': this.update.bindWithEvent(this)
    });
    this.fireEvent('onStart');
  },

  show: function(el, options) {
    $("ModalElement").style.display = "block";
    this.message.empty();
    switch($type(el)) {
      case 'element':
        this.message.adopt(el.clone().cloneEvents(el));
        break;
      case 'string':
        this.message.set('html', el);
        break;
      default:
        return false;
        break;
    }
    if(options && options.width){
      this.pop.setStyle('width',options.width);
    }
    if(options && options.height){
      this.message.setStyle('height',options.height);
    }
    if(!this.isShowing){

      $$('object', 'select').setStyle('visibility', 'hidden');
      $$('body').adopt(this.mask, this.pop);
      this.pop.setStyles({
        'top': window.getScroll().y - this.pop.getSize().y,
        'visibility':'visible',
        'marginLeft': -(this.pop.getSize().x/2)
      });
      this.mask.setStyles({
        'height': window.getSize().y,
        'width': window.getSize().x
      });
      this.fx.mask.start(this.options.maskOpacity);
      this.fx.slide.start((window.getSize().y/2 - this.pop.getSize().y/2)+20);
      this.isShowing = true;
      this.fireEvent('onShow');
    }
  },

  hide: function(e) {
    $("ModalElement").style.display = "none";
    var event = new Event(e).stop();
    $$('object', 'select').setStyle('visibility', 'visible');
    this.fx.slide.cancel();
    this.fx.slide.start(-this.pop.getSize().y).chain(function() {
      this.pop.setStyle('visibility','hidden').dispose();
      this.fx.mask.start(0).chain(function() {
        this.mask.dispose();
        this.isShowing = false;
        this.fireEvent('onHide');
      }.bind(this));
    }.bind(this));
  },

  update: function(e) {
    if(e) e = new Event(e).stop();
    if(this.isShowing) {
      this.fx.slide.cancel();
      var size = window.getSize();
      var scrollSize = window.getScrollSize();
      this.mask.setStyles({
        'height': (size.y > scrollSize.y)?size.y:scrollSize.y,
        'width': size.x
      });
      this.fx.slide.start((window.getSize().y/2 - this.pop.getSize().y/2)+20)
    }
  }
});