$(function() {
  var $ibWrapper  = $('#ib-main-wrapper'),
  Template  = (function() {
    var kinetic_moving = false,
        current = -1,
        isAnimating = false,
        $ibItems = $ibWrapper.find('div.ib-main > a'),
        $ibImgItems = $ibItems.not('.ib-content'),
        imgItemsCount = $ibImgItems.length,

        init = function() {
          $ibImgItems.addClass('ib-image');

          $('#ib-top span.ib-close').bind('click', function() {
            var $this = $(this);
            if ($this.hasClass('img')) {
              $this.removeClass('img');
              closeImgPreview();
            }
            else if($this.hasClass('content')) {
              $this.removeClass('content');
              closeContentPreview();
            }
          });

          loadKinetic();
          initEvents();
        },

        loadKinetic = function() {
          setWrapperSize();
          $ibWrapper.kinetic({
            moved : function() {
              kinetic_moving = true;
            },
            stopped : function() {
              kinetic_moving = false;
            }
          });
        },

        setWrapperSize = function() {
          var containerMargins  = $('#ib-top').outerHeight(true) + $('#header').outerHeight(true) + parseFloat( $ibItems.css('margin-top') );
          $ibWrapper.css( 'height', $('.container').height() - containerMargins )
        },

        initEvents = function() {
          $ibItems.bind('click.ibTemplate', function( event ) {
            if( !kinetic_moving )
              openItem( $(this) );
            return false;
          });
          $(window).bind('resize.ibTemplate', function( event ) {
            setWrapperSize();
            $('#ib-img-preview, #ib-content-preview').css({
              width : $('.container').width(),
              height  : $('.container').height()
            })
          });
        },

        openItem = function( $item ) {
          if( isAnimating ) return false;

          if( $item.hasClass('ib-content') ) {
            isAnimating = true;
            current = $item.index('.ib-content');
            loadContentItem( $item, function() { isAnimating = false; } );
          }
          else {
            isAnimating = true;
            current = $item.index('.ib-image');
            loadImgPreview( $item, function() { isAnimating = false; } );
          }
        },

        loadImgPreview = function( $item, callback ) {
          var largeSrc    = $item.children('img').data('largesrc'),
              description   = $item.children('span').text(),
              largeImageData  = {
                src : largeSrc,
                description : description
              };

          $item.addClass('ib-loading');

          preloadImage( largeSrc, function() {
            $item.removeClass('ib-loading');
            var hasImgPreview = ( $('#ib-img-preview').length > 0 );
            if( !hasImgPreview )
              $('#previewTmpl').tmpl( largeImageData ).insertAfter( $ibWrapper );
            else
              $('#ib-img-preview').children('img.ib-preview-img')
                .attr( 'src', largeSrc )
                .end()
                .find('span.ib-preview-descr')
                .text( description );

            //get dimentions for the image, based on the windows size
            var dim = getImageDim( largeSrc );
            $item.removeClass('ib-img-loading');

            var il = $item.offset().left - $('.container').offset().left;
            var it = $item.offset().top - $('.container').offset().top;

            //set the returned values and show/animate preview
            $('#ib-img-preview').css({
              width : $item.width(),
              height  : $item.height(),
              left  : il,
              top   : it
            }).children('img.ib-preview-img').hide().css({
              width : dim.width,
              height  : dim.height,
              left  : dim.left+20,
              top   : dim.top
            }).fadeIn( 400 ).end().show().animate({
              width : $('.container').width(),
              left  : '20px'
            }, 500, 'easeOutExpo', function() {
              $(this).animate({
                height  : $('.container').height(),
                top   : '60px'
              }, 400, function() {
                var $this = $(this);
                $this.find('span.ib-preview-descr').show();
                var $close = $('#ib-top .ib-close');
                $close.addClass('img');
                $close.show();

                if( imgItemsCount > 1 )
                  $this.find('div.ib-nav').show();
                if( callback ) callback.call();
              });
            });
            if( !hasImgPreview )
              initImgPreviewEvents();
          } );
        },

        // opens one content item (fullscreen)
        loadContentItem = function( $item, callback ) {
          var hasContentPreview = ( $('#ib-content-preview').length > 0 ),
              teaser = $item.children('div.ib-teaser').html(),
              content = $item.children('div.ib-content-full').html(),
              contentData = {
                teaser : teaser,
                content : content
              };
          if( !hasContentPreview )
            $('#contentTmpl').tmpl( contentData ).insertAfter( $ibWrapper );

          var il = $item.offset().left - $('.container').offset().left;
          var it = $item.offset().top - $('.container').offset().top;

          //set the returned values and show/animate preview
          $('#ib-content-preview').css({
            width : $item.width(),
            height  : $item.height(),
            left  : il,
            top   : it
          }).show().animate({
            width : $('.container').width(),
            left  : '20px'
          }, 500, 'easeOutExpo', function() {
            $(this).animate({
              height  : $('.container').height() - 40,
              top   : '60px'
            }, 400, function() {
              var $this = $(this),
              $teaser = $this.find('div.ib-teaser'),
              $content= $this.find('div.ib-content-full'),
              $close  = $('#ib-top span.ib-close');
              if( hasContentPreview ) {
                $teaser.html( teaser )
                $content.html( content )
              }
              $teaser.show();
              $content.show();
              $close.addClass('content');
              $close.show();

              if( callback ) callback.call();
            });
          });
          if( !hasContentPreview )
            initContentPreviewEvents();
        },

        // preloads an image
        preloadImage = function( src, callback ) {
          $('<img/>').load(function(){
            if( callback ) callback.call();
          }).attr( 'src', src );
        },

        // load the events for the image preview : navigation ,close button, and window resize
        initImgPreviewEvents = function() {
          var $preview  = $('#ib-img-preview');
          $preview.find('span.ib-nav-prev').bind('click.ibTemplate', function( event ) {
            navigate( 'prev' );
          }).end().find('span.ib-nav-next').bind('click.ibTemplate', function( event ) {
            navigate( 'next' );
          }).end();

          //resizing the window resizes the preview image
          $(window).bind('resize.ibTemplate', function( event ) {
            var $largeImg = $preview.children('img.ib-preview-img'),
                dim = getImageDim( $largeImg.attr('src') );
            $largeImg.css({
              width : dim.width,
              height : dim.height,
              left : dim.left +20,
              top : dim.top
            })
          });
        },

        // load the events for the content preview : close button
        initContentPreviewEvents  = function() {},

        // navigate the image items in fullscreen mode
        navigate = function( dir ) {
          if( isAnimating ) return false;
          isAnimating = true;
          var $preview = $('#ib-img-preview'),
          $loading = $preview.find('div.ib-loading-large');
          $loading.show();
          if( dir === 'next' ) {
            ( current === imgItemsCount - 1 ) ? current = 0 : ++current;
          }
          else if( dir === 'prev' ) {
            ( current === 0 ) ? current = imgItemsCount - 1 : --current;
          }
          var $item = $ibImgItems.eq( current ),
              largeSrc = $item.children('img').data('largesrc'),
              description = $item.children('span').text();
          var il = $item.offset().left - $('.container').offset().left;
          var it = $item.offset().top - $('.container').offset().top;

          preloadImage( largeSrc, function() {
            $loading.hide();
            //get dimentions for the image, based on the windows size
            var dim = getImageDim( largeSrc );
            $preview.children('img.ib-preview-img')
              .attr( 'src', largeSrc )
              .css({
                width : dim.width,
                height  : dim.height,
                left  : dim.left +20,
                top   : dim.top
              })
              .end()
              .find('span.ib-preview-descr')
              .text( description );
            $ibWrapper.scrollTop( it )
              .scrollLeft( il );
            isAnimating = false;
          });
        },

        // closes the fullscreen image item
        closeImgPreview = function() {
          if( isAnimating ) return false;
          isAnimating = true;

          var $item = $ibImgItems.eq( current );
          var il = $item.offset().left - $('.container').offset().left;
          var it = $item.offset().top - $('.container').offset().top;

          $('#ib-img-preview').find('span.ib-preview-descr, div.ib-nav')
            .hide()
            .end()
            .animate({
              height  : $item.height(),
              top   : it
            }, 500, 'easeOutExpo', function() {
              $(this).animate({
                width : $item.width(),
                left  : il
            }, 400, function() {
              $('#ib-top span.ib-close').hide();
              $(this).fadeOut(function() {isAnimating = false;});
            });
          });
        },

        // closes the fullscreen content item
        closeContentPreview = function() {
          if( isAnimating ) return false;
          isAnimating = true;

          var $item = $ibItems.not('.ib-image').eq( current );
          var il = $item.offset().left - $('.container').offset().left;
          var it = $item.offset().top - $('.container').offset().top;

          $('#ib-content-preview').find('div.ib-teaser, div.ib-content-full')
            .hide()
            .end()
            .animate({
              height  : $item.height(),
              top   : it
            }, 500, 'easeOutExpo', function() {
              $(this).animate({
                width : $item.width(),
                left  : il
            }, 400, function() {
              $('#ib-top span.ib-close').hide();
              $(this).fadeOut(function() {isAnimating = false;});
            });
          });
        },

        // get the size of one image to make it full size and centered
        getImageDim = function( src ) {
          var img = new Image();
          img.src = src;
          var w_w = $('.container').width() - 40,
            w_h = $('.container').height() - 40,
            r_w = w_h / w_w,
            i_w = img.width,
            i_h = img.height,
            r_i = i_h / i_w,
            new_w, new_h,
            new_left, new_top;
          if( r_w > r_i ) {
            new_h = w_h;
            new_w = w_h / r_i;
          }
          else {
            new_h = w_w * r_i;
            new_w = w_w;
          }

          return {
            width : new_w,
            height  : new_h,
            left  : (w_w - new_w) / 2,
            top   : (w_h - new_h) / 2
          };
        };

    return { init : init };
  })();
  Template.init();
});

