/*
 * FOUR WALLS (C) 2010
 * Author: madebycloud.com
 */



;(function($) {
  $(function() {
    
    
    
    $('.clients a').qtip({
      style: {
        background: '#000',
        color: '#fff',
        fontWeight: 'bold',
        border: {
          color: '#000'
        },
        tip: {
          corner: 'bottomMiddle',
          size: {
            x: 14,
            y: 7
          }
        }
      },
      position: {
        corner: {
          target: 'topMiddle',
          tooltip: 'bottomMiddle'
        },
        adjust: {
          y: -1
        }
      }
    });
    
    
    
    /* ---------------------------------------------------------
       GRID - EXTEND CORE
    --------------------------------------------------------- */
    
    $.fn.extend({
      
      /* 
       * hasAttr
       * 
       * Returns true or false is the object has the specified attribute
       */
      hasAttr: function(name) {
        return this.attr(name) !== undefined;
      },
      
      /* 
       * hideProject
       */
      hideProject: function() {
        return this
          .css({
            '-webkit-transform': 'scale(0.5)',
            '-moz-transform': 'scale(0.5)',
            '-o-transform': 'scale(0.5)',
            'transform': 'scale(0.5)'
          })
          .fadeOut(300)
          .attr('data-hidden', true);
      },
      
      /* 
       * showProject
       */
      showProject: function() {
        return this
          .removeAttr('data-hidden')
          .fadeIn(300)
          .css({
            '-webkit-transform': 'scale(1)',
            '-moz-transform': 'scale(1)',
            '-o-transform': 'scale(1)',
            'transform': 'scale(1)'
          });
      },
      
      /* 
       * openProject
       * 
       * Expand the project to the opened state
       */
      openProject: function() {
        var project = this;
        
        // Close currently opened projects
        projects.not(project).closeAll();
        
        if ( ! project.isOpen()) {
          
          project.data('open', true);
          
          var
            opened    = project.find('.opened'),
            closed    = project.find('.closed'),
            slideshow = project.find('.content .slideshow'),
            vimeo     = project.find('.content .vimeo'),
            toggle    = project.find('.toggle-content a');
          
          var images = slideshow.attr('data-images') ? slideshow.attr('data-images').split('|') : [];
          slideshow.once(function() {
            for (var i in images) {
              slideshow.append('<img src="'+images[i]+'" width="460" height="259" />')
            }
          });
          
          if (images.length > 1) {
            var slideshowTimeout;
            slideshow
              .css('cursor', 'pointer')
              .cycle({
                fx: 'scrollLeft'
              })
              .click(function() {
                // Pause slideshow and progress to next slide
                slideshow.cycle('pause').cycle('next');
                
                // Set a timeout that will resume the slideshow
                clearTimeout(slideshowTimeout);
                slideshowTimeout = setTimeout(function() {
                  slideshow.cycle('resume');
                }, 8000);
              });
          }
          
          toggle.once().click(function() {
            if (vimeo.is(':hidden')) {
              // Vimeo
              toggle.toggle();
              slideshow.hide();
              vimeo.show().find('iframe').attr('src', 'http://player.vimeo.com/video/'+vimeo.attr('data-id')+'?autoplay=1');
            }
            else {
              // Slideshow
              toggle.toggle();
              vimeo.hide().find('iframe').attr('src', 'about:blank');
              slideshow.show();
            }
            return false;
          });
          
          project.trigger('project.open.start');
          project.animate({
            width: 700
          }, {
            duration: 300,
            complete: function() {
              project.trigger('project.open.complete');
              //project.find('.title a').maxChars(0);
            }
          });
          
          closed.fadeOut(300);
          opened.delay(300).fadeIn(300);
          
          sortProjects();
          $.scrollTo(project.offset().top - projects.offset().top, 300);
        }
      },
      
      /*
       * closeProject
       * 
       * Contract the project to the closed state
       */
      closeProject: function() {
        var project = this;
        
        if (project.isOpen()) {
          var
            closed = project.children('.closed'),
            opened = project.children('.opened');
          
          project.removeData('open');
          
          // Reset the slideshow
          slideshow = project.find('.content .slideshow').cycle('destroy').unbind('click');
          
          project.trigger('project.close.start');
          project.animate({
            width: 220
          }, {
            duration: 300,
            complete: function() {
              project.trigger('project.close.complete');
              //project.find('.title a').maxChars(18);
            }
          });
          
          //project.find('.title a').maxChars(18);
          
          opened.fadeOut(300);
          closed.delay(300).fadeIn(300, function() {
            
            
            //self.find('.content .vimeo, .toggle-content .slideshow').hide();
            //self.find('.content .slideshow, .toggle-content .vimeo').show();
            
            // Reset to slideshow
            project.find('.content .vimeo, .toggle-content .slideshow').hide().find('iframe').attr('src', 'about:blank');
            project.find('.content .slideshow, .toggle-content .vimeo').show();
          });
          
          sortProjects();
        }
      },
      
      /*
       * closeAll
       * 
       * Close all opened projects
       */
      closeAll: function() {
        return this.filter('.project').filter(function() {
          return $(this).isOpen();
        }).closeProject();
      },
      
      /*
       * isOpen
       * 
       * Returns boolean based on the project state (opened, closed)
       */
      isOpen: function() {
        return this.data('open') == true;
      },
      
      /*
       * projectWidth
       * 
       * Returns the width based on the project state (opened, closed, visible, hidden)
       */
      projectWidth: function() {
        if (this.isOpen()) {
          return 720;
        }
        else if (this.hasAttr('data-hidden')) {
          return 0;
        }
        else {
          return 240;
        }
        
        return width;
      },
      
      /*
       * move
       * 
       * Animates the project to the correct position
       */
      move: function(x, y) {
        var properties = {
          top: y,
          left: x
        }
        
        if (this.hasAttr('data-transition')) {
          return this.animate(properties, {
            duration: 300,
            queue: false
          });
        }
        
        return this.css(properties);
      },
      
      /*
       * maxChars
       * 
       * Crops the internal text of an element to the number of chars required
       */
      maxChars: function(chars, append) {
        if (this.text().length > chars) {
          if (typeof append != 'string') {
            append = '&#8230;';// Ellipse
          }
          
          var str = this.data('fullStr');
          
          if (str == undefined) {
            str = this.text();
            this.data('fullStr', str);
          }
          
          if (chars == undefined || chars == 0) {
            return this.html(str);
          }
          
          var cropped = str.substring(0, chars);
          cropped = cropped.substring(0, cropped.lastIndexOf(' '));
          
          this.html(cropped + append);
        }
        
        return this;
      }
      
    });
    
    
    
    /* ---------------------------------------------------------
       GRID - CREATE VARS AND FUNCTIONS
    --------------------------------------------------------- */
    
    var
      win = $(window),
      nav = $('body > nav'),
      container = $('#projects'),
      projects = container.children('div'),
      
      /*
       * Sorts the project grid
       */
      sortProjects = function() {
        
        /*
        
        As the function loops through the projects it adds them to the first row
        where there is space enough to accomodate it. Where there is not enough
        space the next row is created and the project added to it. This ensures
        that no spaces are left where some projects are expanded and therefore
        occupy a larger space.
        
        The table diagrams below demonstrate various scenarios for grid orders.
        
        -------------------
        |     |     |     |
        |  1  |  2  |  3  |
        |     |     |     |
        -------------------
        |     |     |     |
        |  4  |  5  |  6  |
        |     |     |     |
        -------------------
        
        Consideration is made for opened projects (see below).
        
        -------------------
        |     |     |     |
        |  1  |  3  |  4  |
        |     |     |     |
        -------------------
        |                 |
        |        2        |
        |                 |
        -------------------
        |     |     |
        |  5  |  6  |
        |     |     |
        -------------
        
        */
        
        var
          viewportWidth = win.width(),// The window width
          containerWidth = Math.max(740, viewportWidth - 260),// The width of the project grid
          rows = [],// An array containing column arrays (matrix)
          x = 0,
          y = 0;
        
        // Resize the project grid
        container.width(containerWidth);
        
        // Loop through the projects
        projects.css('position', 'absolute').each(function() {
          
          var
            self = $(this),
            width = self.projectWidth(),
            added = false;// Whether or not the project has been added to a row
          
          // Loop through any existing rows and add the project to the first
          // one with enough space.
          for (var i = 0; i < rows.length; i++) {
            if (rows[i].width + width < containerWidth) {
              rows[i].cols.push(self);
              rows[i].width += width;
              added = true;
              break;
            }
          }
          
          // If there is not enough space in the current rows or no rows have
          // been created, create a new row and add the project to it.
          if ( ! added) {
            rows.push({
              width: width,
              cols: [self]
            });
          }
          
        });
        
        // If the penultimate row has a greater width swap it with the last row
        if (rows.length >= 2 && rows[rows.length - 1].width > rows[rows.length - 2].width) {
          var a = rows.pop();
          var b = rows.pop();
          rows.push(a, b);
        }
        
        // Loop through the rows and columns and position the project
        for (var i in rows) {
          for (var j in rows[i].cols) {
            rows[i].cols[j].move(x, y);
            x +=  rows[i].cols[j].hasAttr('data-hidden') ? 0 : rows[i].cols[j].projectWidth();
          }
          x = 0;
          y+= rows[i].cols[j].outerHeight(true);
        }
      }
    
    
    
    /* ---------------------------------------------------------
       GRID - GO!
    --------------------------------------------------------- */
    
    // First sort
    sortProjects();
    
    // Enabled transitions
    projects.attr('data-transition', true);
    
    
    /* ---------------------------------------------------------
       GRID - CREATE A RELATIONSHIP DICTIONARY FOR TAGS
    --------------------------------------------------------- */
    
    var tagRelationships = {};
    
    $('.project').each(function() {
      
      var
        self = $(this),
        relationship = {},
        tags = self.attr('data-tags');
      
      if (tags != undefined) {
        tags = tags.split('|');
        
        for (var i in tags) {
          relationship[tags[i]] = self;
        }
        
        $.extend(tagRelationships, relationship);
      }
      
    });
    
    
    
    /* ---------------------------------------------------------
       GRID - APPLY SORT FEATURE TO NAV
    --------------------------------------------------------- */
    
    $('#nav .sortby a:not(:first), .project a[href*=/tag/]').each(function() {
      var
        self = $(this),
        tag = self.attr('href').match(/tag\/([^\/]+)\/?/)[1];
      
      self.click(function() {
        projects.closeAll();
        
        projects
          .filter('div[data-tags*='+tag+']')
          .showProject();
        projects
          .filter('div:not([data-tags*='+tag+'])')
          .hideProject();
        
        sortProjects();
        $.scrollTo(0, 300, {
          onAfter: function() {
            $(window).trigger('scroll');
          }
        });
        return false;
      });
    });
    
    $('#nav .sortby a:first').click(function() {
      projects.closeAll();
      projects.showProject();
      $.scrollTo(0, 300, {
        onAfter: function() {
          $(window).trigger('scroll');
        }
      });
      sortProjects();
      return false;
    });
    
    
    
    //$('.project a[href*="/project/"]').each(function() {
    $('.project a.title_permalink').each(function() {
      var
        self = $(this),
        project = self.closest('.project');
      
      self.click(function() {
        project.openProject();
        return false;
      });
    });
    
    
    
    $('.project')
      .has('.title a:not([data-short])')
      .bind('project.open.complete', function() {
        $(this).find('.title a').maxChars(0);
      })
      .bind('project.close.start', function() {
        $(this).find('.title a').maxChars(18);
      })
      .trigger('project.close.start');
    
    
    
    $('.project')
      .has('.title a[data-short]')
      .bind('project.open.complete', function() {
        var self = $(this).find('.title a');
        self.text(self.attr('data-long'));
      })
      .bind('project.close.start', function() {
        var self = $(this).find('.title a');
        self.text(self.attr('data-short'));
      })
      .trigger('project.close.start');
    
    
    
    // Fix stupid Windows font bulls***
    if (navigator.platform.match(/Win/)) {
      $('.project .info p').css('margin-top', 0);
    }
    
    
    
    var
      nav = $('#nav'),
      win = $(window),
      navHeight = nav.outerHeight(true),
      windowHeight = win.height(),
      resizeTimeout;
    
    win
      .resize(function() {
        windowHeight = win.height();
        
        // Use a timeout to delay the sorting of projects to prevent
        // excessive calls to the resource consuming function.
        clearTimeout(resizeTimeout);
        resizeTimeout = setTimeout(sortProjects, 100);
      })    
      .bind("resize scroll", function() {
        // If there is enough space for the whole nav to be shown within the
        // viewport, position the nav to the top of the viewport.
        var navTop = nav.outerHeight(true) <= win.height() ? win.scrollTop() : 0;
        
        if ($.browser.mozilla || navigator.platform == "iPad" || navigator.platform == "iPhone" || navigator.platform == "iPod") {
          nav.animate({top: navTop}, {duration: 300, queue: false});
        }
        else {
          nav.css("top", navTop);
        }
      });
      
    //var resizeTimeout;// Used to create a delay for window resize events
    /*win
      .resize(function() {
        clearTimeout(resizeTimeout);
        resizeTimeout = setTimeout(sortProjects, 100);
      })
      .bind('resize scroll', function() {
        // If there is enough space for the whole nav to be shown within the
        // viewport, position the nav to the top of the viewport.
        nav.css('top', nav.outerHeight(true) <= win.height() ? win.scrollTop() : 0);
      });*/
    
  });
})(window.jQuery);
