
/*
 * SuperMagnusScript 5000
 *
 * Copyright (c) 2010, Magnus Alseth
 * http://www.magnusalseth.com/
 */



/*
 * Class regarding page setup
 */

var PageSetup = {

  gallery: function(category_or_search, search) {
    
    // Setup
    Gallery.setup(category_or_search, search);
    
    // Scroll thumbs
    $(document).mousemove(function(event) {
      ThumbScroll.scrollIt("#slider_inner", event.pageX);
    });
    
    // Thumb links
    $("div.thumb_container div.overlay").live('click', function() {
      var index = $("div.thumb_container div.overlay").index(this);
      Gallery.switchToPhotoViewByIndex(index);
    });
    
    // Previous and next listeners
    $('div#nav_overlay div.previous').live('click', function() {
      PhotoNav.increment(-1);
    });
    $('div#nav_overlay div.next').live('click', function() {
      PhotoNav.increment(1);
    });
    
    // Navigation overlay fade in/out
    $('div#nav_overlay div.active').live('mouseover', function() {
      $(this).find('img').show();
    });
    $('div#nav_overlay div.active').live('mouseout', function() {
      $(this).find('img').hide();
    });
    
    // Active menu click
    $('div#menu li a.active').live('click', function() {
      Gallery.switchToThumbsView();
    });
    
    // Last image click
    $('div#nav_overlay div:not(.active)').live('click', function() {
      Gallery.switchToThumbsView();
    });
  
    // Resize image on window resize
    $(window).resize(function() {
      PhotoScaling.resizeImage();
    });
    
    // clear search input on focus
    $('div#search input').live('focus', function() {
      $(this).val('');
    });
    
  }
  
};



/*
 * Class regarding gallery setup
 */

var Gallery = {
  
  // Constants
  thumbs_wrapper: 'div#slider_outer',
  photo_wrapper: 'div#photo_container',
  
  // Variables
  photo_view: false,
  photos: [],
  thumbs_loaded: false,

  // Setup

  setup: function(category_or_search, search) {
  
    if (search) {
      var JSON_URL = "json/search.json.php?s=" + category_or_search;
    } else {
      var JSON_URL = "json/category.json.php?c=" + category_or_search;
    }
    
    $.getJSON(JSON_URL, function(photos) {
    
      Gallery.photos = photos;
      photo_id = parseInt(window.location.hash.substring(2));
      
      if (photo_id > 0) {
        $(Gallery.thumbs_wrapper).hide();
        ThumbScroll.enabled = false;
        PhotoNav.openPhotoByPhotoID(photo_id);
        Gallery.photo_view = true;
      } else {
        $(Gallery.photo_wrapper).hide();
        ThumbScroll.enabled = true;
        if (Gallery.thumbs_loaded == false) {
          Thumbs.setup();
          Gallery.thumbs_loaded = true;
        }
        Gallery.photo_view = false;
      }

    });
  
  },
  
  switchToPhotoViewByIndex: function(index) {
    
    if (Gallery.photo_view == false) {
      $(Gallery.thumbs_wrapper).fadeOut();
      $(Gallery.photo_wrapper).fadeIn();
      ThumbScroll.enabled = false;
      PhotoNav.openPhotoByIndex(index);
      Gallery.photo_view = true;
    }
  
  },
  
  switchToPhotoViewByPhotoID: function(photo_id) {
    
    if (Gallery.photo_view == false) {
      $(Gallery.thumbs_wrapper).fadeOut();
      $(Gallery.photo_wrapper).fadeIn();
      ThumbScroll.enabled = false;
      PhotoNav.openPhotoByPhotoID(photo_id);
      Gallery.photo_view = true;
    }
  
  },
  
  switchToThumbsView: function() {
    
    if (Gallery.photo_view == true) {
      $(Gallery.thumbs_wrapper).fadeIn();
      $(Gallery.photo_wrapper).fadeOut();
      ThumbScroll.enabled = true;
      if (Gallery.thumbs_loaded == false) {
        Thumbs.setup();
        Gallery.thumbs_loaded = true;
      }
      Gallery.photo_view = false;
      window.location.hash = '#/';
    }
  
  }

};




/*
 * Class regarding loading thumbs into their gallery containers
 */

var Thumbs = {
  
  // Constants
  nr_of_image_streams: 3,
  limit_loading_index_span: true,
  
  // Variables
  stages: [],
  
  // Setup
  
  setup: function() {

    for (var i in Gallery.photos) {
      Thumbs.stages[i] = 0;
    }
    Thumbs.loadThumbs();
      
  },
  
  // Loads images into thumb containers
  
  loadThumbs: function() {

    var load = Thumbs.getImagesToLoad(Thumbs.stages, Thumbs.limit_loading_index_span);
    for (var i in load) {
      Thumbs.stages[load[i]] = 1;
      Thumbs.insertThumb(load[i], function() {
        for (var j in Thumbs.stages) {
          if ($('div.thumb_container:nth-child(' + (parseInt(j) + 1) + ') img').length) {
            Thumbs.stages[j] = 2;
          }
        }
        Thumbs.loadThumbs();
      });
    }
      
  },

  // Insert thumb in HTML by index
  
  insertThumb: function(index, callback) {
  
    var selector = 'div.thumb_container:nth-child(' + (parseInt(index) + 1) + ') div.thumb';
    var url = Gallery.photos[index].thumb_url;
    $("<img />").attr('src', url).load(function() {
      $(selector).hide().append($(this)).fadeIn();
      if (callback) { callback(); }
    });
    
  },

  // Gets array of indexes in photos variable to load thumbs for

  getImagesToLoad: function(stages, limit_loading_index_span) {

    var load = [];
    var j = 0;
    outerLoop:
    for (var i in stages) {
      if (limit_loading_index_span) {
        for (var k in stages) {
          if (stages[k] < 2) {
            if (parseInt(i) - parseInt(k) >= Thumbs.nr_of_image_streams) {
              break outerLoop;
            } else {
              break;
            }
          }
        }
      }
      if (stages[i] < 2) {
        if (stages[i] == 0) {
          load.push(i);
        }
        j++;
        if (j >= Thumbs.nr_of_image_streams) {
          break;
        }
      }
    }
    return load;

  }

};



/*
 * Class regarding photo navigation within a category
 */

var PhotoNav = {
  
  // Constants
  photo_inner_container: 'div#photo_container div.photo_outer div.photo_inner',
  caption_container: 'div#photo_container div.text div.caption',
  description_container: 'div#photo_container div.text div.description',
  
  // Variables
  active_index: 0,
  
  // Call for incrementing photo index
  // Displays new image by photo array index incrementation
  // TODO: CHECK IF ID EXISTS!
  
  openPhotoByPhotoID: function(photo_id) {

    PhotoNav.setActiveIndexByPhotoID(photo_id);
    PhotoNav.displayPhoto(PhotoNav.active_index, false);
    PhotoNav.preloadRelevantImages();
    
  },
  
  openPhotoByIndex: function(index) {
    
    if (index in Gallery.photos) {
      PhotoNav.active_index = index;
      PhotoNav.displayPhoto(PhotoNav.active_index, false);
      PhotoNav.preloadRelevantImages();
    }
    
  },
  
  increment: function(increment) {

    var index = PhotoNav.active_index + increment;
    if (index in Gallery.photos) {
      PhotoNav.active_index = index;
      PhotoNav.displayPhoto(PhotoNav.active_index, true);
      PhotoNav.openPhotoByIndex();
    }
    
  },

  // Sets active photos array index by photo ID
  
  setActiveIndexByPhotoID: function(photo_id) {
  
    for (var i in Gallery.photos) {
      if (Gallery.photos[i].id == photo_id) {
        PhotoNav.active_index = parseInt(i);
      }
    }
    
  },

  // Deals with all HTML and CSS
  
  displayPhoto: function(index, animate_resizing) {
    
    // Sets location hash
    window.location.hash = '#/' + Gallery.photos[PhotoNav.active_index].id;

    // Controlls photo navigation classes
    if ((PhotoNav.active_index - 1) in Gallery.photos) {
      $('div#nav_overlay div.previous').addClass('active');
    } else {
      $('div#nav_overlay div.previous').removeClass('active').find('img').hide();
    }
    if ((PhotoNav.active_index + 1) in Gallery.photos) {
      $('div#nav_overlay div.next').addClass('active');
    } else {
      $('div#nav_overlay div.next').removeClass('active').find('img').hide();
    }
    
    // Clears stuff
    $(PhotoNav.photo_inner_container).find('img').remove();
    $(PhotoNav.caption_container).empty();
    $(PhotoNav.description_container).empty();
    
    // Sets container sizes
    PhotoScaling.setImageSizes(Gallery.photos[index].width, Gallery.photos[index].height, animate_resizing, function() {
    
      // Sets caption and description
      $(PhotoNav.caption_container).html(Gallery.photos[index].caption);
      $(PhotoNav.description_container).html(Gallery.photos[index].description);
      
      // Loads image
      $("<img />").attr('src', Gallery.photos[index].photo_url).bind('load', function() {
        $(PhotoNav.photo_inner_container).hide().empty().append($(this)).fadeIn();
      });
      
    });

  },
  
  // Preloads next and previous images
  // Possible improvement: Waiting for images to load before loading the next
  
  preloadRelevantImages: function() {
  
    var preload_indexes = [PhotoNav.active_index + 1, PhotoNav.active_index - 1];
    var cache = [];
    for (var i in preload_indexes) {
      if (preload_indexes[i] in Gallery.photos) {
        var cacheImage = document.createElement('img');
        cacheImage.src = Gallery.photos[preload_indexes[i]].photo_url;
        cache.push(cacheImage);
      }
    }
    
  }

};



/*
 * Class regarding scrolling thumbs
 */

var ThumbScroll = {

  // Constants
  mouseBoxMargins: 100,
  enabled: true,
  
  // Call on mouse move
  // Scrolls thumbs
  
  scrollIt: function(selector, page_x) {
    
    if (ThumbScroll.enabled) {
      var scroll_to = Math.min(ThumbScroll.getScrollToValue($(selector).width(), page_x), 0);
      $(selector).stop(true, false).animate({left: scroll_to}, "slow", "easeOutQuart");
    }
  
  },

  // Returns the css left value for the thumbs container
  
  getScrollToValue: function(width, page_x) {
  
    var scroll_to;
    if (page_x < ThumbScroll.mouseBoxMargins) {
      scroll_to = 0;
    } else if ($(window).width() - page_x < ThumbScroll.mouseBoxMargins) {
      scroll_to =  $(window).width() - width;
    } else {
      scroll_to = -Math.round((width - $(window).width()) * (page_x - ThumbScroll.mouseBoxMargins) / ($(window).width() - 2 * ThumbScroll.mouseBoxMargins));
    }
    return scroll_to;
    
  }
  
};



/*
 * Class regarding adapting photo and caption size to window size
 */

var PhotoScaling = {
  
  // Constants
  subtract_from_width: 60,
  subtract_from_height: 135,
  image_min_h: 240,
  photo_outer_container: 'div#photo_container div.photo_outer',
  text_container: 'div#photo_container div.text',
  
  // Variables
  image_orig_w: 0,
  image_orig_h: 0,
  
  // Call before image load
  // Sets image size variables and resizes container
  
  setImageSizes: function(width, height, animate, callback) {
  
    PhotoScaling.image_orig_w = parseInt(width);
    PhotoScaling.image_orig_h = parseInt(height);
    PhotoScaling.resizeImage(animate, callback);
    
  },
  
  // Call on window resize
  // Resizes container
  
  resizeImage: function(animate, callback) {
  
    var image_max_w = Math.max($(window).width() - PhotoScaling.subtract_from_width, PhotoScaling.image_min_h * PhotoScaling.image_orig_w / PhotoScaling.image_orig_h);
    var image_max_h = Math.max($(window).height() - PhotoScaling.subtract_from_height, PhotoScaling.image_min_h);
    var image_lengths = PhotoScaling.getProperSizes(PhotoScaling.image_orig_w, PhotoScaling.image_orig_h, image_max_w, image_max_h);
    var resize_necessary = (image_lengths[0] !== $(PhotoScaling.photo_outer_container).width() || image_lengths[1] !== $(PhotoScaling.photo_outer_container).height());
    
    if (animate && resize_necessary) {
      $(PhotoScaling.text_container).animate({'width': image_lengths[0]}, "fast");
      $(PhotoScaling.photo_outer_container).animate({'width': image_lengths[0], 'height': image_lengths[1]}, "fast", function() {
        if (callback) { callback(); }
      });
    } else {
      $(PhotoScaling.text_container).css({'width': image_lengths[0]});
      $(PhotoScaling.photo_outer_container).css({'width': image_lengths[0], 'height': image_lengths[1]});
      if (callback) { callback(); }
    }
    
  },

  // Returns adapted image sizes
  
  getProperSizes: function(orig_w, orig_h, max_w, max_h) {
  
    var new_size = [];
    if (orig_w > max_w || orig_h > max_h) {
      if ((max_w / max_h) > (orig_w / orig_h)) {
        new_size[0] = Math.round(max_h * (orig_w / orig_h));
        new_size[1] = max_h;
      } else {
        new_size[0] = max_w;
        new_size[1] = Math.round(max_w * (orig_h / orig_w));
      }
    } else {
      new_size[0] = orig_w;
      new_size[1] = orig_h;
    }
    return new_size;
    
  }

};
