/*========================================================================

FBF.Lightbox
============

Author: Terry Morgan <terry.morgan@fivebyfivedigital.com>
Version: 0.2

Requirements: Prototypejs 1.7

Provides lightbox functionality for the following
scenarios:

- Single images
- Groups of images
- Single videos (youtube)
- Groups of videos (youtube)
- Inline content

Options
=======

lightboxHtml
Markup pattern for lightbox overlay - must contain a div.fg

imageDataHTML
Markup pattern for image details displayed in lightbox. Currently
includes image title, image credit (ie. photographer), twitter and
facebook sharelinks. This is needs to be made dynamic.

overlayOpacity
The opacity of the "blackout" overlay.
Must be between 0 (fully transparent) and 1 (fully opaque)

videoDims
A object conatining the dimensions of the videos if used

videoDataHTML
Same as imageDataHTML but for videos

videoEmbedHTML
Markup pattern for the embed HTML used for the video options

========================================================================*/
var FBF = window.FBF||{};

FBF.Lightbox = function(){
  var container,
      contentTemplate,
      clicked,
      defaultItem = false,
      imageGroups = $H(),
      groupIndex,
      itemDataContainer,
      imageDataTemplate,
      overlayPanelInnerFg,
      items,
      lightboxType,
      options,
      overlay,
      overlayPanel,
      overlayPanelClose,
      overlayPanelInner,
      overlayPanelInnerFg,
      nextButton,
      nextImageDims = { height : 0, width : 0 },
      numInGroup,
      ph,
      prevButton,
      pv,
      viewportDims,
      videoDataTemplate,
      videoGroups = $H(),
      visible;

  function build() {
    overlay = new Element('div', { 'id' : 'overlay' }).setStyle({
      opacity : options.overlayOpacity
    }).hide();

    Element.insert(document.body, overlay);

    overlayPanelClose = new Element('a').addClassName('close').update('Close');
    overlayPanelClose.writeAttribute('title', 'Close this window');
    overlayPanel = new Element('div', { 'id' : 'overlay-panel' }).hide();

    overlayPanelInner = new Element('div', { 'id' : 'overlay-panel-inner' }).update(options.lightboxHtml);
    overlayPanel.insert(overlayPanelInner);

    Element.insert(document.body, overlayPanel);

    overlayPanelInnerFg = overlayPanelInner.down('div.fg');
    ph = parseInt(overlayPanelInnerFg.getStyle('paddingLeft'), 10) + parseInt(overlayPanelInnerFg.getStyle('paddingRight'), 10);
    pv = parseInt(overlayPanelInnerFg.getStyle('paddingTop'), 10) + parseInt(overlayPanelInnerFg.getStyle('paddingBottom'), 10);

    contentTemplate = new Template(options.lightboxHtml);

    items = container.select('a.lightbox');

    itemDataContainer = new Element('div').addClassName('item-data').update(overlayPanelClose);
    overlayPanel.insert(itemDataContainer);

    imageDataTemplate = new Template(options.imageDataHTML);
    videoDataTemplate = new Template(options.videoDataHTML);

    insertNavButtons();

    getImageGroups();
    getVideoGroups();

    Event.observe(document.body, 'click', onClick);

    if(defaultItem) {
      viewportDims = document.viewport.getDimensions();
      var attrs = {
        href : defaultItem.href,
        title: defaultItem.title,
        id : defaultItem.id,
        rel : 'image'
      };

      clicked = new Element('a', attrs).addClassName('lightbox').update('<span class="credit">'+defaultItem.credit+'</span>').hide();
      Element.insert(document.body, clicked);

      lightboxType = getLightboxType(clicked.rel);

      if(defaultItem.type == 'image') {
        loadImg(defaultItem.href);
      } else if(defaultItem.type == 'video') {
        insertVideo(getEmbedHTML(defaultItem.href));
      }

      showLightbox();
    }
  }

  function getDocHeight() {
    var D = document;
    return Math.max(
      Math.max(D.body.scrollHeight, D.documentElement.scrollHeight),
      Math.max(D.body.offsetHeight, D.documentElement.offsetHeight),
      Math.max(D.body.clientHeight, D.documentElement.clientHeight)
    );
  }

  function getEmbedHTML(_embedUrl) {
    var embedTemplate = new Template(options.videoEmbedHTML);
    return embedTemplate.evaluate({
      embedUrl : _embedUrl,
      height : options.videoDims.height,
      width : options.videoDims.width
    });
  }

  function getItemData() {
    if(lightboxType.type == 'image' || lightboxType.type == 'video') {
      var _link = clicked;
    } else if(lightboxType.type == 'imageGroup') {
      var _link = imageGroups.get(lightboxType.groupName)[groupIndex];
    } else if(lightboxType.type == 'videoGroup') {
      var _link = videoGroups.get(lightboxType.groupName)[groupIndex];
    }

    return {
      credit : _link.down('span.credit').innerHTML,
      fbShare : 'http://www.facebook.com/sharer.php?u='+window.location.href+'share:'+_link.id.split('-')[1],
      title : _link.title,
      twShare : 'http://twitter.com?status='+window.location.href+'share:'+_link.id.split('-')[1]
    }
  }

  function getImageGroups() {
    var groupImages = items.findAll(function(el) {
      return el.match('a[rel^=imageGroup]');
    });

    if(groupImages.length > 0) {
      groupImages.each(function(el) {
        var groupName = getLightboxType(el.rel).groupName;
        if(imageGroups.keys().include(groupName)){
          imageGroups.get(groupName).push(el);
        } else {
          var groupItems = [el];
          imageGroups.set(groupName, groupItems);
        }
      });
    }
  }

  function getLightboxType(rel) {
    var r = rel.split(':');
    return {
      type : r[0],
      groupName : r[1]
    };
  }

  function getVideoGroups() {
    var groupVideos = items.findAll(function(el) {
      return el.match('a[rel^=videoGroup]');
    });

    if(groupVideos.length > 0) {
      groupVideos.each(function(el) {
        var groupName = getLightboxType(el.rel).groupName;
        if(videoGroups.keys().include(groupName)){
          videoGroups.get(groupName).push(el);
        } else {
          var groupItems = [el];
          videoGroups.set(groupName, groupItems);
        }
      });
    }
  }

  function hideLightbox() {
    visible = false;
    overlay.hide()
    overlayPanelInnerFg.update(""); // clear out lightbox contents
    overlayPanel.hide();
  }

  function insertNavButtons() {
    nextButton = new Element('div').addClassName('next').update('<a>Next</a>').hide();
    prevButton = new Element('div').addClassName('prev').update('<a>Prev</a>').hide();

    overlayPanel.insert(nextButton);
    overlayPanel.insert(prevButton);
  }

  function insertVideo(emdedHTML) {
    var panelTop = document.viewport.getScrollOffsets().top + (viewportDims.height / 2) - (options.videoDims.height / 2);

    var panelWidth = options.videoDims.width+ph;
    var panelHeight = options.videoDims.height+pv;

    overlayPanel.setStyle({
      height : panelHeight+'px',
      marginLeft : -(options.videoDims.width / 2)+'px',
      top : Math.round(Math.max((document.viewport.getScrollOffsets().top + 10), panelTop))+'px',
      width : panelWidth+'px'
    });

    updateItemData(options.videoDims.width);

    overlayPanelInnerFg.update(emdedHTML);

    if(lightboxType.type == 'videoGroup'){
      if(videoGroups.keys().include(lightboxType.groupName)){
        var groupVideos = videoGroups.get(lightboxType.groupName);
        numInGroup = groupVideos.length;
        if(numInGroup > 1){
          if(groupIndex == 0) {
            prevButton.hide();
            nextButton.show();
          } else if(groupIndex == numInGroup-1) {
            prevButton.show();
            nextButton.hide();
          } else {
            prevButton.show();
            nextButton.show();
          }
        }
      }
    }
  }

  function loadInlineContent(contentId){
    var theContent = $(contentId);
    var contentLayout = theContent.getLayout();

    var panelWidth = contentLayout.get('padding-box-width');
    var panelHeight = contentLayout.get('padding-box-height');

    inlineContentWrapper = new Element('div').addClassName('inline-content-wrapper').update(theContent.innerHTML);
    overlayPanelInnerFg.update(inlineContentWrapper);

    var _ph = parseInt(inlineContentWrapper.getStyle('paddingRight'), 10) + parseInt(inlineContentWrapper.getStyle('paddingLeft'), 10);
    var _pv = parseInt(inlineContentWrapper.getStyle('paddingTop'), 10) + parseInt(inlineContentWrapper.getStyle('paddingBottom'), 10);

    var panelTop = document.viewport.getScrollOffsets().top + (viewportDims.height / 2) - (panelHeight / 2);

    overlayPanel.setStyle({
      height : (panelHeight+_pv)+'px',
      marginLeft : -((panelWidth+_ph) / 2)+'px',
      top : Math.round(Math.max((document.viewport.getScrollOffsets().top + 10), panelTop))+'px',
      width : (panelWidth+_ph)+'px'
    });
  }

  function loadImg(href) {
    var img = new Image();
    img.onload = onImgLoad.curry(img);
    img.src = href;
  }

  function onClick(e) {
    if(clicked = e.findElement('a.lightbox')) {
      e.stop();
      var contentId = clicked.hash.substring(1);
      lightboxType = getLightboxType(clicked.rel);
      viewportDims = document.viewport.getDimensions();

      switch(lightboxType.type) {
        case 'image':
          prevButton.hide();
          nextButton.hide();
          loadImg(clicked.href);
          showLightbox();
          break;

        case 'video':
          prevButton.hide();
          nextButton.hide();
          insertVideo(getEmbedHTML(clicked.href));
          showLightbox();
          break;

        case 'imageGroup':
          groupIndex = imageGroups.get(lightboxType.groupName).indexOf(clicked);
          loadImg(clicked.href);
          showLightbox();
          break;

        case 'videoGroup':
          groupIndex = videoGroups.get(lightboxType.groupName).indexOf(clicked);
          insertVideo(getEmbedHTML(clicked.href));
          showLightbox();
          break;

        case 'inline':
          loadInlineContent(contentId);
          showLightbox();
          break;
      }
    } else if(clicked = e.findElement('div.next a')) {
      e.stop();
      navigate(1);
    } else if(clicked = e.findElement('div.prev a')) {
      e.stop();
      navigate(-1);
    } else if(clicked = e.findElement('a.share')) {
      e.stop();
      open(clicked.href);
    } else if(visible && (!e.target.descendantOf(overlayPanel) || e.target == overlayPanelClose)) {
      e.stop();
      clicked = e.target;
      hideLightbox();
    }
  }

  function onImgLoad(image) {
    var href = image.src;
    var imgHeight = image.height;
    var imgWidth = image.width;

    if(imgWidth > viewportDims.width-ph) {
      var newWidth = Math.round(viewportDims.width-ph-50);
      var newHeight = Math.round((imgHeight/imgWidth)*newWidth);

      imgHeight = newHeight;
      imgWidth = newWidth;
    }

    if(imgHeight > viewportDims.height-pv) {
      var newHeight = Math.round(viewportDims.height-pv-50);
      var newWidth = Math.round((imgWidth/imgHeight)*newHeight);

      imgHeight = newHeight;
      imgWidth = newWidth;
    }

    var panelWidth = imgWidth+ph;
    var panelHeight = imgHeight+pv;

    var panelTop = document.viewport.getScrollOffsets().top + (viewportDims.height / 2) - (panelHeight / 2);

    overlayPanel.setStyle({
      height : panelHeight+'px',
      marginLeft : -(panelWidth/2)+'px',
      top : Math.round(Math.max((document.viewport.getScrollOffsets().top + 10), panelTop))+'px',
      width : panelWidth+'px'
    });

    var img = new Template('<img src="#{src}" alt="" id="lightboxImg" height="#{height}" width="#{width}" />');
    overlayPanelInnerFg.update(img.evaluate({
      src : href,
      height : imgHeight,
      width : imgWidth
    }));

    updateItemData(imgWidth);

    if(lightboxType.type == 'imageGroup'){
      if(imageGroups.keys().include(lightboxType.groupName)){
        var groupImages = imageGroups.get(lightboxType.groupName);
        numInGroup = groupImages.length;
        if(numInGroup > 1){
          if(groupIndex == 0) {
            prevButton.hide();
            nextButton.show();
          } else if(groupIndex == numInGroup-1) {
            prevButton.show();
            nextButton.hide();
          } else {
            prevButton.show();
            nextButton.show();
          }
        }
      }
    }
  }

  function navigate(offset){
    var nextToShow = groupIndex + offset;

    if(nextToShow > 0 || nextToShow < numInGroup-1) {
      groupIndex = nextToShow;
      overlayPanelInner.hide();
      if(lightboxType.type == 'imageGroup') {
        loadImg(imageGroups.get(lightboxType.groupName)[groupIndex].href);
      } else if(lightboxType.type == 'videoGroup') {
        insertVideo(getEmbedHTML(videoGroups.get(lightboxType.groupName)[groupIndex].href));
      }
      overlayPanelInner.show();
    }
  }

  function showLightbox() {
    visible = true;

    overlay.setStyle({
      height: getDocHeight()+'px',
      width: viewportDims.width+'px'
    });

    overlay.show()
    overlayPanel.show();
  }

  function updateItemData(width) {
    if(lightboxType.type == 'imageGroup' || lightboxType.type == 'image') {
      itemDataContainer.update(imageDataTemplate.evaluate(getItemData()));
    } else if (lightboxType.type == 'videoGroup' || lightboxType.type == 'video') {
      itemDataContainer.update(videoDataTemplate.evaluate(getItemData()));
    }
    itemDataContainer.insert(overlayPanelClose);
    itemDataContainer.setStyle({
      width: width+'px'
    });
  }

  return {
    initialize: function(element, _options) {
      options = Object.extend({
        lightboxHtml : '<div class="fg"></div><div class="bg"></div>',
        imageDataHTML :  '<span class="image-title">#{title}</span><span class="image-credit">#{credit}</span><div class="share-links"><div><a href="#{fbShare}" class="facebook share">Share on Facebook</a></div><div><a href="#{twShare}" class="twitter share">Share on Twitter</a></div></div>',
        overlayOpacity : 0.5,
        videoDims : {
          height : 385,
          width : 640
        },
        videoDataHTML :  '<span class="image-title">#{title}</span><span class="image-credit">#{credit}</span><div class="share-links"><div><a href="#{fbShare}" class="facebook share">Share on Facebook</a></div><div><a href="#{twShare}" class="twitter share">Share on Twitter</a></div></div>',
        videoEmbedHTML : '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="#{width}" height="#{height}"><param name="movie" value="#{embedUrl}&color1=0x323232&color2=0x242424"></param><param name="allowFullScreen" value="false"></param><param name="wmode" value="transparent"></param><param name="allowscriptaccess" value="always"></param><embed src="#{embedUrl}&color1=0x323232&color2=0x242424" type="application/x-shockwave-flash" wmode="transparent" allowscriptaccess="always" allowfullscreen="false" width="#{width}" height="#{height}"></embed></object>'
      }, _options||{});

      container = $(element);

      if (typeof window.defaultItem != 'undefined') {
        defaultItem = window.defaultItem;
      }

      build();
    }
  }
}();
