var TemplatePreview = Class.create({
  initialize: function(thumbnailImg) {
    this.thumbnailImg = $(thumbnailImg);
    this.previewImg = null;

    this.previewWnd = null;
    this.previewTitle = null;
    this.previewProgressBar = null;

    this.dimensions = null;

    /* Init event handlers */
    this.thumbnailImg.observe('mouseover', this.onMouseOver.bindAsEventListener(this));
    this.thumbnailImg.observe('mouseout', this.onMouseOut.bindAsEventListener(this));

    // Cache the bound onMouseMove handler for Event.stopObserving method
    this.onMouseMoveHandler = function(event) {
      this.onMouseMove(event);
    }.bindAsEventListener(this);
  },

  build: function() {
    this.previewWnd = new Element('div', {id:'tplPreview', display: 'none'});
    this.previewTitle = new Element('h2', {id:'tplPreviewTitle'});
    this.previewProgressBar = new Element('div', {
      id:'tplPreviewProgressBar'
    }).update('Loading template preview...');

    var tplPreviewHead = new Element('div', {id:'tplPreviewHead'}).appendChild(this.previewTitle);
    var tplPreviewBody = new Element('div', {id:'tplPreviewBody'});
    tplPreviewBody.appendChild(this.getPreviewImg());
    tplPreviewBody.appendChild(this.previewProgressBar);

    this.previewWnd.appendChild(tplPreviewHead);
    this.previewWnd.appendChild(tplPreviewBody);

    document.body.appendChild(this.previewWnd);
  },

  getPreviewImg: function() {
    if (this.previewImg == null) {
      this.previewImg = new Element('img', {
        id: 'tplPreviewImage',
        src: this.thumbnailImg.getAttribute('preview-src'),
        width: this.thumbnailImg.getAttribute('preview-width'),
        height: this.thumbnailImg.getAttribute('preview-height')
      });

      this.previewImg.observe('load', function(event){
        this.previewProgressBar.hide();
      }.bindAsEventListener(this));

      this.previewProgressBar.show();
    }

    return this.previewImg;
  },

  init: function() {
    if ($('tplPreview') != null) {
      this.previewWnd = $('tplPreview');
      this.previewTitle = $('tplPreviewTitle');
      this.previewProgressBar = $('tplPreviewProgressBar');
      $('tplPreviewImage').replace(this.getPreviewImg());
    } else {
      this.build();
    }

    this.previewTitle.update(this.thumbnailImg.getAttribute('preview-title'));
  },

  show: function() {
    this.init();
    if (this.dimensions == null) {
      this.dimensions = this.previewWnd.getDimensions();
    }

    var viewport = document.viewport.getDimensions();
    if (this.dimensions.width <= viewport.width
          && this.dimensions.height <= viewport.height) {
      this.previewWnd.show();
    }
  },

  hide: function() {
    this.previewWnd.hide();
    this.previewWnd.style.top = -this.dimensions.height + 'px';
    this.previewWnd.style.left = -this.dimensions.width + 'px';
  },

  onMouseOver: function(event) {
    this.thumbnailImg.observe('mousemove', this.onMouseMoveHandler);
    this.show();
  },

  onMouseOut: function(event) {
    this.thumbnailImg.stopObserving('mousemove', this.onMouseMoveHandler);
    this.hide();
  },

  onMouseMove: function(event) {
    var viewport = Object.extend(
      document.viewport.getDimensions(),
      document.viewport.getScrollOffsets()
    );

    Object.extend(viewport, {
      bottom: viewport.top + viewport.height,
      right: viewport.left + viewport.width
    });

    var mouse = {
      x: event.pointerX() - viewport.left,
      y: event.pointerY() - viewport.top,
      offset: 24
    };

    var wndTop = 0;
    var wndLeft = 0;
    var valignMiddle = false;

    if (mouse.y + mouse.offset < (viewport.height - this.dimensions.height) / 2) {
      // valign previewWnd bottom
      wndTop = mouse.y + mouse.offset;
    } else if (mouse.y - mouse.offset > (viewport.height + this.dimensions.height) / 2) {
      // valign previewWnd top
      wndTop = mouse.y - mouse.offset - this.dimensions.height;
    } else {
      // valign previewWnd middle
      wndTop = (viewport.height - this.dimensions.height) / 2;
      valignMiddle = true;
    }

    if (!valignMiddle
        && ((mouse.x + mouse.offset > (viewport.width - this.dimensions.width) / 2)
          && (mouse.x - mouse.offset < (viewport.width + this.dimensions.width) / 2))) {
      wndLeft = (viewport.width - this.dimensions.width) / 2;
    } else {
      if (mouse.x > viewport.width / 2) {
        // align previewWnd left
        wndLeft = mouse.x - mouse.offset - this.dimensions.width;
      } else {
        // align previewWnd right
        wndLeft = mouse.x + mouse.offset;
      }
    }

    wndLeft += viewport.left;
    wndTop += viewport.top;

    this.previewWnd.style.top = wndTop + 'px';
    this.previewWnd.style.left = wndLeft + 'px';
  }
});



Event.observe(window, 'load', function() {
  $$('img[preview="on"]').each(function(thumbnailImg) {
    new TemplatePreview(thumbnailImg);
  });
});

