var Video,
  Carousel, carousel, 
  Parallax, parallax,
  Overbox, overbox,
  Toggle, toggle,
  Popover, popover;

Video = (function() {
  function Video(id) {
    this.playtime = 0;
    this.player = $f( id );

    var self = this;
    this.player.addEvent('ready', function() {
      if( parseInt(self.playtime) === 0 ) return false;
      self.set_seek();
    })
  }

  Video.prototype.pause = function() {
    var self = this;

    this.player.api('pause');
    this.player.api('getCurrentTime', function(val, id) {
      self.playtime = val;
    });
  }

  Video.prototype.set_seek = function() {
    this.player.api('seekTo', this.playtime);
    this.pause();
  }

  return Video;
})();

Carousel = (function() {
  function Carousel(data) {
    this.elements = {
      selector: data.slide,
      holder: $(data.slide).parent(),
      container: $(data.container || $(data.slide).parent()),
      base: $(data.slide),
      current: $(data.slide).first(),
      next: "",
      added: ""
    };

    this.cpos = 0;
    this.apos;

    this.amount = 5;
    this.opacity = 0.6;
    this.duration = 800;

    this.container_width;
    this.transitionable = false;
    this.parallax = false;
  }

  Carousel.prototype.init = function() {
    this.elements.holder.prepend( this.elements.base.slice(this.elements.base.length - Math.floor( this.amount / 2 ), this.elements.base.length) );

    var _j = 0;
    this.removal(_j, $(this.elements.selector));

    this.elements.container.attr( 'id', 'built' );
    this.container_width = this.position_container();

    $(this.elements.selector).not('#current')
      .css({ opacity: 0 })
      .fadeTo( this.duration * 2, this.opacity );

    this.transitionable = true;
  }

  // recursively detach from dom.
  Carousel.prototype.removal = function(position, elements) {
    $(elements[position]).append( $('<div class="cover"></div>') );
    if( position >= this.amount ) $(elements[position]).detach();
    if( position < elements.length ) return this.removal(position + 1, elements);
  }

  Carousel.prototype.video = function(element) {
    if( element.data("video") || !element.find('iframe').is('*') ) return false;

    element.data( "video", new Video(element.find('iframe').attr('id')) )
  }

  Carousel.prototype.position_container = function() {
    var contain_width;

    contain_width = this.elements.current.outerWidth( true ) * this.amount;

    this.elements.container.css({
      width: contain_width,
      left: - (contain_width - $('html, body').width()) / 2
    });

    return contain_width;
  }

  Carousel.prototype.navigate = function(selected) {
    if( selected.attr('id') === "current" || !this.transitionable ) return false;
    this.transitionable = false;

    this.cpos = Math.floor( this.amount / 2 ) + this.elements.base.index( this.elements.current );
    this.apos = ( this.cpos < this.amount )? this.cpos + 1 : this.cpos - this.amount;

    this.dir = this.direction( selected );
    this.elements.next = (this.dir)? this.elements.current.next() : this.elements.current.prev();
    this.add_slide();

    video = this.elements.current.data("video");
    if( video ) video.pause();

    return true;
  }

  Carousel.prototype.direction = function(clicked) {
    // right or next
    if( $(this.elements.selector).index(clicked) > (this.amount / 2) ) return true; 
    // left or previous
    return false; 
  }

  Carousel.prototype.transition = function() {
    if( this.parallax ) this.parallax.transition( this.dir );
    this.transition_current({ element: this.elements.current, id: '', opacity: this.opacity })
    this.transition_current({ element: this.elements.next, id: 'current', opacity: 1 });
    this.transition_slide();
  }

  Carousel.prototype.transition_current = function(data) {
    data.element.fadeTo(this.duration, data.opacity || this.opacity, function() {
      data.element.attr('id', data.id || '');
    });
  }

  Carousel.prototype.add_slide = function() {
    this.elements.added = $(this.elements.base[this.apos]);
    this.elements.added.css({
      'margin-left': ( this.dir )? 0 : -( this.container_width / this.amount ), 
      opacity: this.opacity
    });

    // fixes ie cache issue.
    if( this.elements.added.find('iframe').is('*') ) {
      this.elements.added.find('iframe').attr('src', function(i, val) {
        return val + "&time=" + new Date().getTime();
      })
    }

    ( this.dir )? this.elements.added.appendTo(this.elements.holder) : this.elements.added.prependTo(this.elements.holder);
  }

  Carousel.prototype.transition_slide = function() {
    var self, offset, removed;

    self = this;
    offset = ( this.dir )? -( this.container_width / this.amount ) : 0;

    this.elements.current = this.elements.next; 

    $(this.elements.selector).first().animate({
      'margin-left': offset
    }, this.duration, function() {
      removed = ( self.dir )? $(this) : $(self.selector).last();
      removed.detach().css({
        opacity: self.opacity,
        'margin-left': 0
      });

      self.transitionable = true;
    })
  }

  return Carousel;
})();

Parallax = (function() {
  // todo: add min/max for random amount on each layer, .data method on each element
  function Parallax(set, initial_class, min, max) {
    this.elements = $(set);
    this.classname = initial_class || 'para';
    this.min = min || 150;
    this.max = max || 750;

    if( $.support.transition ) this.setup();
  };

  Parallax.prototype.setup = function() {
    var self = this;

    $.each(this.elements, function(iter, item) {
      $(item).data({ offset: self.random(), current: 0 });
    })
  }

  Parallax.prototype.random = function() {
    return Math.floor(Math.random() * (this.max - this.min) + this.min)
  }

  Parallax.prototype.transition = function(right) {
    this.elements.addClass(this.classname);
    var set_offset;

    $.each(this.elements, function(iter, item) {
      set_offset = (right)? $(item).data().offset : - ($(item).data().offset);

      $(item).css({ "background-position": set_offset + $(item).data().current })
      $(item).data().current = set_offset + $(item).data().current;
    })
  }

  return Parallax;
})();

$.support.transition = (function(){ 
  var thisBody = document.body || document.documentElement,
  thisStyle = thisBody.style,
  support = thisStyle.transition !== undefined || thisStyle.WebkitTransition !== undefined || thisStyle.MozTransition !== undefined || thisStyle.MsTransition !== undefined || thisStyle.OTransition !== undefined;
    
  return support; 
})();

Number.prototype.lesser = function(compare) {
  if(compare < this) return compare;
  return this;
}

Number.prototype.greater = function(compare) {
  if(compare > this) return compare;
  return this;
}

String.prototype.url_from_opt = function( array, sep ) {
  // from key, val pairs.
  var index, str;
  
  str = this.toString()
  for ( index in array ) {
    str += (index + sep + array[index] + '&' );
  }
  return str;
}

Overbox = (function() {
  function Overbox(data) {
    this.elements = data.elements;
    this.current = {
      element: "",
      src: "",
      likecount: 0,
      id: 0,
      width: 0,
      height: 0
    }
    this.box = {
      closeClass: data.closeClass || 'closed',
      background: data.background,
      container: data.container,
      x: 0,
      y: 0,
      open: false,
      media: data.container.find('.sm'),
      fb_url: data.container.find('#fb_share').attr('href'),
      fb_opt: { },
      twitter_button: data.container.find('.twitter-share-button')
    };
  }

  Overbox.prototype.init = function() {
    this.switchable = false;
    this.fb_parse_url();
  }

  Overbox.prototype.lay = function(element) {
    this.box.open = true;

    this.current_properties(element);

    this.build_properties();
    this.build_dimensions();

    this.box.container.removeClass( this.box.closeClass );
    this.box.background.removeClass( this.box.closeClass );
    this.switchable = true;
  }

  Overbox.prototype.navigate = function(direction) {
    this.switchable = false;
    var npos, epos;
    epos = this.elements.index( this.current.element );

    if( direction === 'left') {
      npos = ( epos - 1 < 0 )? this.elements.length - 1 : epos - 1;
    } else {
      npos = ( epos + 1 >= this.elements.length )? 0 : epos + 1;
    }

    this.lay( $(this.elements[npos]) );
  }

  Overbox.prototype.close = function() {
    this.box.container.addClass( this.box.closeClass );
    this.box.background.addClass( this.box.closeClass );
    this.box.open = false;
  }

  Overbox.prototype.getDimensions = function() {
    var w_width, w_height;

    w_width = this.current.width.greater( $(window).width() );
    w_height = this.current.height.greater( $(window).height() ) - 40;

    this.box.x = (0).greater(( w_width - this.current.width ) / 2);
    this.box.y = (0).greater(( w_height - this.current.height ) / 2);
  }

  Overbox.prototype.build_dimensions = function() {
    this.getDimensions();

    this.box.container.css({
      left: this.box.x,
      top: this.box.y,
      width: $(window).outerWidth().lesser( this.current.width ) - 8,
      height: ( this.current.height.lesser( $(window).height() ) )
    });
  }

  Overbox.prototype.build_properties = function() {
    this.box.container.find('img').attr({
      src: this.current.src
    });

    this.set_media();
  }

  Overbox.prototype.current_properties = function(element) {
    this.current.element = element;
    this.current.src = element.data().src;
    this.current.width = element.data().width;
    this.current.height = element.data().height;
    this.box.fb_opt.u = element.data().src;
    this.box.twitter_button.removeAttr('data-rendering')
    this.box.twitter_button.attr({ 'data-url' : this.current.src })
  }

  Overbox.prototype.fb_parse_url = function() {
    var url = this.box.fb_url.split('.php?')[1].split('&');

    this.fb_params( url, 0, this.box.fb_opt );
    this.set_media();
  }

  Overbox.prototype.fb_params = function(el, i, target) {
    target[ el[i].split('=')[0] ] = el[i].split('=')[1] || '';
    if( i + 1 < el.length ) return this.fb_params(el, i + 1, target);
  }

  Overbox.prototype.set_media = function() {
    this.fb_url = 'http://www.facebook.com/sharer.php?'.url_from_opt( this.box.fb_opt, '=' );
    this.box.container.find('#fb_share').attr('href', this.fb_url);

    if(twttr.widgets) {
      this.box.media.find('iframe').remove()
      this.box.media.append( this.box.twitter_button )
      twttr.widgets.load();
    }
  }

  return Overbox;
}())

Toggle = (function() {
  function Toggle(data) {
    this.elements = data.elements;
    this.toggleclass = 'collapsed';
    this.duration = 600;
    this.transitionable = true;
  }

  Toggle.prototype.swap = function(clicked) {
    if( !this.transitionable || !clicked.parent().hasClass( this.toggleclass ) ) return false;
    this.transitionable = false;

    var self = this;

    this.elements.slideToggle(this.duration, function() {
      $(this).parent().toggleClass(self.toggleclass);
      self.transitionable = true;
    })
  }

  Toggle.prototype.toggle = function(els, iter) {
    $(els[iter]).parent().toggleClass(this.toggleclass);
    if(iter != this.elements.length) return this.toggle(els, iter + 1);
  }

  return Toggle;
}())

Popover = (function() {
  function Popover(data, params) {
    this.state = false;
    this.element = data.element;  
    this.timer = 1500;
    this.fadeTime = 250;
    this.timeout;
  }

  Popover.prototype.init = function( callback ) {
    if( this.initialized ) return;

    if(callback) callback()
    this.initialized = true;
  }

  Popover.prototype.open = function( callback ) {
    if( this.state ) return;
    var self = this;

    this.element.fadeIn( this.fadeTime, function() {
      if(callback) callback()
    });

    this.state = true;
  }

  Popover.prototype.close = function( callback ) {
    this.element.fadeOut( this.fadeTime, function() {
      if(callback) callback()
    });

    this.state = false;
  }

  Popover.prototype.init_close = function( callback ) {
    var self = this;

    if( this.timeout ) clearTimeout( this.timeout );
    this.state = false;

    this.timeout = setTimeout(function() {
      if( !self.state ) {
        self.close(function() {
          if(callback) callback()
        })
      }
    }, this.timer)
  }

  return Popover;
}())

jQuery(document).ready(function() {
  // handlers for video gallery.
  parallax = new Parallax($('#mountains, #trees_back, #animals, #trees_front'));
  carousel = new Carousel({
    slide: 'section.videos article', 
    container: 'section.videos'
  });

  $('iframe').load(function(response, status, xhr) {
    carousel.video($(this).parent());
    if( !carousel.transitionable) carousel.transition();
  })

  var navigate;

  $('section.videos article').click(function(e) {
    navigate = carousel.navigate($(this));
    
    if( carousel.elements.added && !carousel.elements.added.find('iframe').is('*') && navigate ) {
      carousel.transition();
    }
    
    e.stopPropagation();
    e.preventDefault();
  });

  carousel.init();
  carousel.parallax = parallax;

  // handlers for photo gallery.
  var k = new Kibo(),

  overbox = new Overbox({
    elements: $('a.lightbox_link'),
    container: $('#overbox'),
    background: $('#underbox')
  });

  overbox.init();

  $('a.lightbox_link').click(function(e) {
    overbox.lay($(this));
  
    e.stopPropagation();
    e.preventDefault();
  })

  $('#underbox, #overbox a.close_button').click(function(e) {
    overbox.close();

    e.stopPropagation();
    e.preventDefault();
  })

  k.up(['left', 'right'], function(e, key) {
    if( !overbox.switchable ) return false;

    overbox.navigate( k.lastKey() );
  })

  k.up('esc', function() {
    if( !overbox.box.open ) return false;
    
    overbox.close();
  })

  $(window).resize(function(e) {
    carousel.contain_width = carousel.position_container();

    if( overbox.box.open ) overbox.build_dimensions();

    e.stopPropagation();
    e.preventDefault();
  })

  // toggle view
  toggle = new Toggle({
    elements: $('.elements, #photos_holder')
  })

  $('h1:not(.logo)').click(function(e) {
    toggle.swap($(this));

    e.stopPropagation();
    e.preventDefault();
  })

  // email popover
  popover = new Popover({ element: $('form#email') });

  $('a.email').hover(function(e) {
    popover.open();

    e.stopPropagation();
    e.preventDefault();
  }, function(e) {
    popover.init_close();

    e.stopPropagation();
    e.preventDefault();
  })
  
  $('a.email').click(function(e) {
    if( popover.state ) {
      $('form#email').submit();
    }
    popover.open();

    e.stopPropagation();
    e.preventDefault();
  })

  $('form#email').hover(function(e) {
    popover.open();

    e.stopPropagation();
    e.preventDefault();
  }, function(e) {
    popover.init_close();
  
    e.stopPropagation();
    e.preventDefault();
  })

  var default_email = $('form#email input').val();

  $('form#email input').focusin(function(e) {
    popover.open();
    popover.focused = true;

    if( $(this).val() === default_email ) $(this).val('');

    e.stopPropagation();
    e.preventDefault();
  }).focusout(function(e) {
    var self = this;

    popover.init_close( function() {
      if( $(self).val() === '' ) $(self).val( default_email );
    });
  
    e.stopPropagation();
    e.preventDefault();
  })

  $('form#email').submit(function() {
    var form = $(this);

    $.ajax({
      type: "post",
      url: $(this).attr('action'),
      data: $(this).serializeArray(),
      success: function( data ) {
        data = JSON.parse(data);

        if( data.incorrect || data.empty ) {
          if( form.hasClass('error') ) return false;

          form.addClass('error');
        } else {
          form.removeClass('error')
          popover.close(function() {
            form.find('input').val( default_email );
          });
        }
      }
    })

    return false;
  })
})

