/*
        Moognify 3.0 

        Description:
                Enlarges images with an OS X style effect.
                
        Requirements:
                Mootools 1.2 or later.
        
        Arguments:
                element - the image to enlarge
                options - the options
                
        Options:
                duration: miliseconds, duration of the enlarge effect. Defaults to 300.
                borderDuration: miliseconds, duration of the border effect. Defaults to 200.
                borderOpacity: opacity of the image border, defaults to 0.8.
                source: path to the large image. Optional.
                altText: The alt text will be used as image descrition if set to true. Defaults to true.
                text: Image description, overrides altText. Optional.
                
        CSS:
                The border styling is controlled via the css class ".moognifyBorder". 
                The borde has no default styling and will appear transparent til you set a background color.
                
        Example:
                <img src='imageThumb.jpg' alt='' onclick='new Moognify(this,{duration: 500, source: "imageLarge.jpg", text: "This is one of my pictures."});' />
*/

Asset.image('/resources/i/moognify-waiter.gif');

var Moognify = new Class({
  
  Implements: Options,
  
  Binds: ['click', 'loaded'],
  
  options: {
    source: '',
    overlay: true,
    waiterOpacity: 0.5,
    borderClass: 'moognify-border-zoomed',
    overlayClass: 'moognify-overlay',
    zoomDuration: 300
  },
  
  initialize: function(element, options) {
    this.element = $(element);
    this.setOptions(options);
    if (this.options.overlay) {
      this.overlay = new Overlay($merge({className: this.options.overlayClass}, this.options.overlay)).addEvent('click', this.click);
    }
    this.bounds = null;
    if (next = this.element.getFirst()) {
      if (next.get('tag') == 'img') {
        this.bounds = next.getCoordinates();
      }
    }
    if (this.bounds == null) {
      this.bounds = this.element.getCoordinates();
    }
    this.build();
    this.load();
  },
  
  build: function() {
    this.waiter = new Element('div', {
      'styles': {
        'position': 'absolute',
        'left': this.bounds.left,
        'top': this.bounds.top,
        'width': this.bounds.width,
        'height': this.bounds.height,
        'z-index': '99',
        'opacity': this.options.waiterOpacity
      },
      'class': 'moognify-waiter'
    }).injectInside(document.body);
    
    this.border = new Element('div', {
      'styles': {
        'position': 'absolute',
        'left': 0,
        'top': 0,
        'display': 'none'
      },
      'class': 'moognify-border'
    }).injectInside(document.body);
    
    this.image = new Element('img').addEvents({
      'load': this.loaded,
      'click': this.click
    }).injectInside(this.border);
  },
  
  load: function() {
    if (this.options.source != '') {
      this.image.src = this.options.source;
    }
  },
  
  loaded: function() {
    this.waiter.setStyle('display', 'none');
    this.zoomIn();
  },

  click: function() {
    this.zoomOut();
  },
  
  zoomIn: function() {
    this.border.setStyles({
      'display': 'block',
      'opacity': 0
    });
    
    this.size = {
      width: this.image.width,
      height: this.image.height 
    };
    
    if (this.size.width > this.size.height) {
      this.size.new_height = this.bounds.height;
      this.size.new_width = Math.round(this.size.width / (this.size.height / this.bounds.height));
    } else {
      this.size.new_width = this.bounds.width;
      this.size.new_height = Math.round(this.size.height / (this.size.width / this.bounds.width));
    }
    
    this.offset = {
      x: ((this.bounds.width - this.size.new_width) / 2) - this.border.getStyle('padding-left').toInt(),
      //y: /*((this.bounds.height - (this.size.height / this.zoomFactor())) / 2) -*/  -this.border.getStyle('padding-top').toInt()
      y: ((this.bounds.height - this.size.new_height) / 2) - this.border.getStyle('padding-top').toInt()
    };
    
    this.border.setStyles({
      'display': 'block',
      'position': 'absolute',
      'left': this.bounds.left + this.offset.x,
      'top': y = this.bounds.top + this.offset.y,
      /*'width': this.bounds.width,
      'height': this.bounds.height,*/
      'opacity': 0
    });
    this.image.setStyles({
      'width': this.size.new_width,
      'height': this.size.new_height
    });

    var windowSize = window.getSize();

    this.top = ((windowSize.y - this.size.height) / 2) /*+ window.getScroll().y*/;
    this.left = (windowSize.x / 2) - (this.size.width / 2);
    
    if (this.top < 20) this.top = 20;
    if (this.left < 20) this.left = 20;
    
    this.top += window.getScroll().y;

    /*new Fx.Tween(this.border, {duration: 100}).start('opacity', 1).chain(function() {
      if (this.overlay) this.overlay.show();
      new Fx.Morph(this.border, {duration: this.options.zoomDuration}).start({
        'left': this.left,
        'top': this.top,
        'width': this.size.width,
        'height': this.size.height
      });
      new Fx.Morph(this.image, {duration: this.options.zoomDuration}).
        addEvent('onComplete', function() {
          this.border.morph('.' + this.options.borderClass);
        }.bind(this)).
        start({
          'width': this.size.width,
          'height': this.size.height
        });
    }.bind(this));*/
    
    new Fx.Tween(this.border, {duration: 100}).start('opacity', 1);
    
    if (this.overlay) this.overlay.show();
    this.hideObjects();
    new Fx.Morph(this.border, {duration: this.options.zoomDuration}).start({
      'left': this.left,
      'top': this.top/*,
      'width': this.size.width,
      'height': this.size.height*/
    });
    new Fx.Morph(this.image, {duration: this.options.zoomDuration}).
      addEvent('onComplete', function() {
        this.border.morph('.' + this.options.borderClass);
      }.bind(this)).
      start({
        'width': this.size.width,
        'height': this.size.height
      });
  },
  
  zoomOut: function() {
    this.border.morph('.moognify-border');
    if (this.overlay) this.overlay.hide();
    new Fx.Morph(this.border, {duration: this.options.zoomDuration}).start({
      'left': this.bounds.left + this.offset.x,
      'top': this.bounds.top + this.offset.y,
      'width': this.bounds.width,
      'height': this.bounds.height
    });
    new Fx.Morph(this.image, {duration: this.options.zoomDuration}).
      addEvent('onComplete', function() {
        this.border.set('tween', {duration: 150}).tween('opacity', 0);
        this.destroy.delay(300, this);
        this.showObjects();
      }.bind(this)).
      start({
        'width': this.size.new_width,
        'height': this.size.new_height
      });
  },
  
  destroy: function() {
    if (this.waiter) {
      this.waiter.destroy();
      this.waiter = null;
    }
    if (this.border) {
      this.border.destroy();
      this.border = null;
      this.image = null;
    }
    if (this.overlay) {
      this.overlay.destroy();
      this.overlay = null;
    }
  },
  
  hideObjects: function() {
    //var objects = document.body.getElementsByTagName('object');
    var objects = document.getElements('.uncoverable');
    for (var i = 0, l = objects.length; i < l; i++) {
      objects[i].setAttribute('hidden', 'true');
      $(objects[i]).setStyle('visibility', 'hidden');
    }
  },
  
  showObjects: function() {
    //var objects = document.body.getElementsByTagName('object');
    var objects = document.getElements('.uncoverable');
    for (var i = 0, l = objects.length; i < l; i++) {
      if (objects[i].getAttribute('hidden') == 'true') {
        $(objects[i]).setStyle('visibility', 'visible');
      }
    }
  }
  
});
