/**
 * Script: Slideshow.Emsys.js Slideshow.Emsys - Emsys extension for Slideshow,
 * includes zooming and panning effects.
 * 
 * License: MIT-style license.
 * 
 * Copyright: Copyright (c) 2008 [Aeron
 * Glemann](http://www.electricprism.com/aeron/).
 * 
 * Dependencies: Slideshow.
 */

Slideshow.Emsys = new Class(
    {
    Extends: Slideshow,
    options:
        {
        pan: [100, 100],
        zoom: [50, 50]
        },

    /**
     * Constructor: initialize Creates an instance of the Slideshow
     * class.
     * 
     * Arguments: element - (element) The wrapper element. data - (array
     * or object) The images and optional thumbdims, captions and links
     * for the show. options - (object) The options below.
     * 
     * Syntax: var myShow = new Slideshow.Emsys(element, data, options);
     */

    initialize: function(el, data, options)
    {
      options.overlap = true;
      options.resize = true;
      options.slide = 0;
      options.thumbdims = true;
      [
      'pan',
      'zoom'
      ].each(function(p)
      {
        if ($chk(this[p]))
        {
          if ($type(this[p]) != 'array')
            this[p] = [this[p], this[p]];

          this[p].map(function(n)
          {
            return(n.toInt() || 0).limit(0, 100);
          });
        }
      }, options);
      this.setOptions(options);
      this.slideshow = $(el);

      if (!this.slideshow)
        return;
      this.slideshow.set('styles',
          {
          'display': 'block',
          'position': 'relative',
          'z-index': 0
          });

      var match = window.location.href.match(this.options.match);
      this.slide = (this.options.match && match) ? match[1].toInt() : this.options.slide;
      this.counter = this.delay = this.transition = 0;
      this.direction = 'left';
      this.paused = false;

      if (!this.options.overlap)
        this.options.duration *= 2;
      var anchor = this.slideshow.getElement('a') || new Element('a');

      if (!this.options.href)
        this.options.href = anchor.get('href') || '';

      if (this.options.hu.length && !this.options.hu.test(/\/$/))
        this.options.hu += '/';

      if (this.options.fast === true)
        this.options.fast = 2;

      // styles

      var keys = ['slideshow', 'first', 'prev', 'play', 'pause', 'next', 'last', 'images', 'captions', 'controller',
          'thumbdims', 'hidden', 'visible', 'inactive', 'active', 'loader'];

      var values = keys.map(function(key, i)
      {
        return this.options.classes[i] || key;
      }, this);
      this.classes = values.associate(keys);
      this.classes.get = function()
      {
        var str = '.' + this.slideshow;

        for (var i = 0, l = arguments.length; i < l; i++)
            str += ('-' + this[arguments[i]]);
        return str;
      }.bind(this.classes);

      // data

      if (!data)
      {
        this.options.hu = '';
        data = {};
        var x = this.classes.get('thumbdims') + ' img';
        var thumbdims = this.slideshow.getElements(x);
        this.slideshow.getElements(this.classes.get('images') + ' img').each(function(img, i)
        {
          var src = img.get('src');
          var caption = $pick(img.get('alt'), img.get('title'), '');
          var parent = img.getParent();
          var properties = (parent.get('tag') == 'a') ? parent.getProperties : {};
          var href = img.getParent().get('href') || '';
          var thumbdim = (thumbdims[i]) ? thumbdims[i].get('src') : '';
          data[src] =
              {
              'caption': caption,
              'href': href,
              'thumbdim': thumbdim
              };
        });
      }

      var loaded = this.load(data);

      if (!loaded)
        return;

      // events

      this.events = $H(
          {
          'keydown': [],
          'keyup': [],
          'mousemove': []
          });

      var keyup = function(e)
      {
        switch (e.key)
        {
          case 'left':
              this.prev(e.shift);
              break;

          case 'right':
              this.next(e.shift);
              break;

          case 'p':
              this.pause();
              break;
        }
      }.bind(this);
      this.events.keyup.push(keyup);
      document.addEvent('keyup', keyup);

      // required elements

      var el = this.slideshow.getElement(this.classes.get('images'));
      var images = (el) ? el.empty() : new Element('div',
          {
          'class': this.classes.get('images').substr(1)
          }).inject(this.slideshow);

      var div = images.getSize();
      this.height = this.options.height || div.y;
      this.width = this.options.width || div.x;
      images.set(
          {
          'styles':
              {
              'display': 'block',
              'height': this.height,
              'overflow': 'hidden',
              'position': 'relative',
              'width': this.width
              }
          });

      this.slideshow.store('images', images);
      this.a = this.image = this.slideshow.getElement('img') || new Element('img');

      if (Browser.Engine.trident && Browser.Engine.version > 4)
        this.a.style.msInterpolationMode = 'bicubic';
      this.a.set('styles',
          {
          'display': 'none',
          'position': 'absolute',
          'zIndex': 1
          });

      this.b = this.a.clone();
      [
      this.a,
      this.b
      ].each(function(img)
      {
        anchor.clone().cloneEvents(anchor).grab(img).inject(images);
      });

      // optional elements

      if (this.options.captions)
        this._captions();

      if (this.options.controller)
        this._controller();

      if (this.options.loader)
        this._loader();

      if (this.options.thumbdims)
        this._thumbdims();

      var x = 1;

      // begin show

      this._preload();
    },

    /**
     * Public method: load Loads a new data set into the show: will stop
     * the current show, rewind and rebuild thumbdims if applicable.
     * 
     * Arguments: data - (array or object) The images and optional
     * thumbdims, captions and links for the show.
     * 
     * Syntax: myShow.load(data);
     */

    load: function(data)
    {
      this.firstrun = true;
      this.showed =
          {
          'array': [],
          'i': 0
          };

      if ($type(data) == 'array')
      {
        this.options.captions = false;
        data = new Array(data.length).associate(data.map(function(image, i)
        {
          return image + '?' + i
        }));
      }
      this.data =
          {
          'images': [],
          'captions': [],
          'hrefs': [],
          'thumbdims': []
          };

      for (var image in data)
      {
        var obj = data[image] || {};
        var caption = (obj.caption) ? obj.caption.trim() : '';
        var href = (obj.href) ? obj.href.trim() : ((this.options.linked) ? this.options.hu + image : this.options.href);
        var thumbdim = caption;
        this.data.images.push(image);
        this.data.captions.push(caption);
        this.data.hrefs.push(href);
        this.data.thumbdims.push(thumbdim);
      }

      if (this.options.random)
        this.slide = $random(0, this.data.images.length - 1);

      // only run when data is loaded dynamically into an existing
      // slideshow instance

      if (this.options.thumbdims && this.slideshow.retrieve('thumbdims'))
        this._thumbdims();

      if (this.slideshow.retrieve('images'))
      {
        [
        this.a,
        this.b
        ].each(function(img)
        {
          [
          'morph',
          'tween'
          ].each(function(p)
          {
            if (this.retrieve(p))
              this.get(p).cancel();
          }, img);
        });
        this.slide = this.transition = 0;
        this.go(0);
      }
      return this.data.images.length;
    },

    /**
     * Private method: preload Preloads the next slide in the show, once
     * loaded triggers the show, updates captions, thumbdims, etc.
     */

    _preload: function(fast)
    {
      if (!this.preloader)
      {
        var x =
            {
            'onload': function()
            {
              this.store('loaded', true);
            }
            };
        this.preloader = new Asset.image(this.options.hu + this.data.images[this.slide], x);
      }
      var thisloaded = this.preloader.retrieve('loaded');

      if (this.preloader.retrieve('loaded') && $time() > this.delay && $time() > this.transition)
      {
        if (this.stopped)
        {
          if (this.options.captions)
            this.slideshow.retrieve('captions').get('morph').cancel().start(this.classes.get('captions', 'hidden'));
          this.pause(1);

          if (this.end)
            this.fireEvent('end');
          this.stopped = this.end = false;
          return;
        }
        this.image = (this.counter % 2) ? this.b : this.a;
        this.image.set('styles',
            {
            'display': 'block',
            'height': 'auto',
            'visibility': 'hidden',
            'width': 'auto',
            'zIndex': this.counter
            });

        [
        'src',
        'height',
        'width'
        ].each(function(prop)
        {
          this.image.set(prop, this.preloader.get(prop));
        }, this);
        this._resize(this.image);
        this._center(this.image);
        var anchor = this.image.getParent();

        if (this.data.hrefs[this.slide])
          anchor.set('href', this.data.hrefs[this.slide]);

        else
          anchor.erase('href');
        var text = (this.data.captions[this.slide])
            ? this.data.captions[this.slide].replace(/<.+?>/gm, '').replace(/</g, '&lt;').replace(/>/g,
                '&gt;').replace(/"/g, "'") : '';
        this.image.set('alt', text);

        if (this.options.titles)
          anchor.set('title', text);

        if (this.options.loader)
          this.slideshow.retrieve('loader').fireEvent('hide');

        if (this.options.captions)
          this.slideshow.retrieve('captions').fireEvent('update', fast);
         if (this.options.thumbdims)
         this.slideshow.retrieve('thumbdims').fireEvent('update',  fast);
        this._show(fast);
        this._loaded();
      }

      else
      {
        if ($time() > this.delay && this.options.loader)
          this.slideshow.retrieve('loader').fireEvent('show');
        this.timer = (this.paused && this.preloader.retrieve('loaded')) ? null : this._preload.delay(100, this, fast);
      }
    },

    _buildMBDiv: function(i)
    {
      var mb = $("mb_" + this.data.captions[i].toLowerCase());
      var wellnessdims = $('wellnessdims');

      var el = $('mb_show');
      var mbShow = (el) ? el.empty() : new Element('div',
          {
          'id': 'mb_show'
          });

      mbShow.setStyles(
          {
          'position': 'relative',
          'display': 'none',
          'overflow': 'hidden'
          });

      var mbImage = new Element('div',
          {
          'id': 'mb_image'
          });

      var showImage = this.preloader.clone();
      showImage.inject(mbImage);
      // showImage.setStyles({'height':200, 'width':300, 'left':50});
      showImage.set('styles',
          {
          'height': 250,
          'width': 300,
          'position': 'relative',
          'left': '50px'
          });

      var mbFiller = new Element('div',
          {
          'id': 'mb_filler'
          });

      mbFiller.set('html', '<br/><br/>');
      var mbSpan = new Element('div',
          {
          'id': 'mb_span'
          });

      mbSpan.set('styles',
          {
          'font-weight': 'bold'
          });

      mbSpan.set('html', mb.get('html'));
      mbImage.inject(mbShow);
      mbFiller.inject(mbShow);
      mbSpan.inject(mbShow);
      mbShow.inject(wellnessdims);
      var x = 1;
    },

    /**
     * Private method: thumbdims Builds the optional thumbdims element,
     * adds interactivity. This method can safely be removed if the
     * thumbdims option is not enabled.
     */

    _thumbdims: function()
    {
      if (this.options.thumbdims === true)
        this.options.thumbdims = {};
      var pel = this.slideshow.getParent();
      var thumbdims = pel.getElement(this.classes.get('thumbdims'));
      thumbdims.setStyle('overflow', 'hidden');
      // x = el.empty();
      /*
       * var thumbdims = (el) ? el.empty() : new Element('div',
       * {'class':
       * this.classes.get('thumbdims').substr(1)}).inject(this.slideshow);
       * thumbdims.setStyle('overflow', 'hidden'); var ul = new
       * Element('ul', {'tween': {'link':
       * 'cancel'}}).inject(thumbdims);
       */
      var ul = thumbdims.getElement("ul");
      var lis = ul.getChildren("li");
      this.data.thumbdims.each(function(thumbdim, i)
      {
        var li = lis[i];
        var a = li.getElement("a");
        var aevents =
            {
            'click': function(i)
            {
              this.go(i);
              var caption = "#mb_"
                  + this.data.captions[i].toLowerCase();
              this._buildMBDiv(i);
              doMediaboxInline(this.preloader, "#mb_show", '400', '440');
              return false;
            }.pass(i, this),
            'loaded': function()
            {
              this.data.thumbdims.pop();

              if (!this.data.thumbdims.length)
              {
                var div = thumbdims.getCoordinates();
                var props = thumbdims.retrieve('props');
                var limit = 0, pos = props[1], size = props[2];
                thumbdims.getElements('li').each(function(li)
                {
                  var li = li.getCoordinates();

                  if (li[pos] > limit)
                    limit = li[pos];
                }, this);
                thumbdims.store('limit', div[size] + div[props[0]] - limit);
              }
            }.bind(this)
            };
        a.addEvents(aevents);
        a.set('href', this.options.hu + this.data.images[i]);
        a.set('morph', $merge(this.options.thumbdims,
            {
            'link': 'cancel'
            }));
      }, this);

      var x = 1;
      thumbdims.set('events',
          {
          'scroll': function(n, fast)
          {
            var div = this.getCoordinates();
            var ul = this.getElement('ul').getPosition();
            var props = this.retrieve('props');
            var axis = props[3], delta, pos = props[0], size = props[2], value;
            var tweenobj = this.getElement('ul').get('tween',
                {
                'property': pos
                });
            var tween = tweenobj;
            if (tweenobj.tween)
            	{
            	tween = tweenobj.tween;
                tween.options.property = pos;
            	}
            // var tween =
            // this.getElement('ul').get('tween');
            // if (tween.tween) tween = tween.tween;
            // tween.options.property = "top";
            if ($chk(n))
            {
              var li = this.getElements('li')[n].getCoordinates();
              delta = div[pos] + (div[size] / 2) - (li[size] / 2) - li[pos]
              value = (ul[axis] - div[pos] + delta).limit(this.retrieve('limit'), 0);

              if (fast)
                tween.set(value);

              else
                tween.start(value);
            }

            else
            {
              var area = div[props[2]] / 3, page = this.retrieve('page'), velocity = -0.2;

              if (page[axis] < (div[pos] + area))
                delta = (page[axis] - div[pos] - area) * velocity;

              else if (page[axis] > (div[pos] + div[size] - area))
                delta = (page[axis] - div[pos] - div[size] + area) * velocity;

              if (delta)
              {
                value = (ul[axis] - div[pos] + delta).limit(this.retrieve('limit'), 0);
                tween.set(value);
              }
            }
          }.bind(thumbdims),
          'update': function(fast)
          {
            var thumbdims = this.slideshow.retrieve('thumbdims');
            var as = thumbdims.getElements('a');
            as.each(function(a, i)
            {
              if (i == this.slide)
              {
                if (!a.retrieve('active', false))
                {
                  a.store('active', true);
                  var active = this.classes.get('thumbdims', 'active');

                  if (fast)
                    a.get('morph').set(active);

                  else
                    a.morph(active);
                }
              }

              else
              {
                if (a.retrieve('active', true))
                {
                  a.store('active', false);
                  var inactive = this.classes.get('thumbdims', 'inactive');

                  if (fast)
                    a.get('morph').set(inactive);

                  else
                    a.morph(inactive);
                }
              }
            }, this);

            if (!thumbdims.retrieve('mouseover'))
              thumbdims.fireEvent('scroll', [this.slide, fast]);
          }.bind(this)
          })

      var div = thumbdims.getCoordinates();
      thumbdims.store('props', (div.height > div.width)
          ? ['top', 'bottom', 'height', 'y'] : ['left', 'right', 'width', 'x']);

      var mousemove = function(e)
      {
        var div = this.getCoordinates();

        if (e.page.x > div.left && e.page.x < div.right && e.page.y > div.top && e.page.y < div.bottom)
        {
          this.store('page', e.page);

          if (!this.retrieve('mouseover'))
          {
            this.store('mouseover', true);
            this.store('timer', function()
            {
              this.fireEvent('scroll');
            }.periodical(50, this));
          }
        }

        else
        {
          if (this.retrieve('mouseover'))
          {
            this.store('mouseover', false);
            $clear(this.retrieve('timer'));
          }
        }
      }.bind(thumbdims);
      this.events.mousemove.push(mousemove);
      document.addEvent('mousemove', mousemove);
      this.slideshow.store('thumbdims', thumbdims);
    }
    });
