/*
 * jQuery hashchange event - v1.3 - 7/21/2010
 * http://benalman.com/projects/jquery-hashchange-plugin/
 * 
 * Copyright (c) 2010 "Cowboy" Ben Alman
 * Dual licensed under the MIT and GPL licenses.
 * http://benalman.com/about/license/
 */
(function($,e,b){var c="hashchange",h=document,f,g=$.event.special,i=h.documentMode,d="on"+c in e&&(i===b||i>7);function a(j){j=j||location.href;return"#"+j.replace(/^[^#]*#?(.*)$/,"$1")}$.fn[c]=function(j){return j?this.bind(c,j):this.trigger(c)};$.fn[c].delay=50;g[c]=$.extend(g[c],{setup:function(){if(d){return false}$(f.start)},teardown:function(){if(d){return false}$(f.stop)}});f=(function(){var j={},p,m=a(),k=function(q){return q},l=k,o=k;j.start=function(){p||n()};j.stop=function(){p&&clearTimeout(p);p=b};function n(){var r=a(),q=o(m);if(r!==m){l(m=r,q);$(e).trigger(c)}else{if(q!==m){location.href=location.href.replace(/#.*/,"")+q}}p=setTimeout(n,$.fn[c].delay)}$.browser.msie&&!d&&(function(){var q,r;j.start=function(){if(!q){r=$.fn[c].src;r=r&&r+a();q=$('<iframe tabindex="-1" title="empty"/>').hide().one("load",function(){r||l(a());n()}).attr("src",r||"javascript:0").insertAfter("body")[0].contentWindow;h.onpropertychange=function(){try{if(event.propertyName==="title"){q.document.title=h.title}}catch(s){}}}};j.stop=k;o=function(){return a(q.location.href)};l=function(v,s){var u=q.document,t=$.fn[c].domain;if(v!==s){u.title=h.title;u.open();t&&u.write('<script>document.domain="'+t+'"<\/script>');u.close();q.location.hash=v}}})();return j})()})(jQuery,this);

$.extend($.easing, {
  easeInOutCubic: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t + b;
		return c/2*((t-=2)*t*t + 2) + b;
	}
});

$(function() {
  function tmpl(string, data) {
    return string.replace(/\$\{(.+?)\}/g, function(match, key) { return data[key] });
  }
  
  function rand(max) {
    return Math.floor(Math.random() * max);
  }
  
  // Shuffle array. 
  // If firstIndex and howMany given: Shuffle only howMany elements starting from firstIndex (see Array.splice)
  function shuffle(array, firstIndex, howMany) {
    if (firstIndex !== undefined && howMany !== undefined) {
      var elementsToShuffle = array.slice(firstIndex, firstIndex + howMany);
      shuffle(elementsToShuffle);
      array.splice.apply(array, [firstIndex, howMany].concat(elementsToShuffle));
    } else {
      var numShuffles = array.length * 10;
      for (var i = 0; i < numShuffles; i++) {
        var j = rand(array.length), temp = array[0];
        array[0] = array[j];
        array[j] = temp;
      }
    }
  }

  function initJobAd() {
    var body = $("body"), 
      ad = $("#job"), 
      height = ad.outerHeight() ,
      toggle = $("#job-ad-toggle"),
      toggleIcon = toggle.find(".tipogram").first(),
      fader = $("<div/>").hide().appendTo(body),
      faderTimeout,
      visible = false;
    
    function initFader() {
      fader.css({position: "absolute", left: 0, top: 0, overflow: "hidden", background: "#000", zIndex: 98}).
        width($(document).width()).
        height($(document).height());
    }
    
    function initPersonInfo() {
      $(".person").hover(
        function() { 
          if ($(this).data("timeout")) window.clearTimeout($(this).data("timeout"));
          $(this).closest(".signature").find(".info").hide();
          $(this).find(".info").fadeIn("fast"); 
        },
        function() { 
          var el = $(this);
          if (el.data("timeout")) window.clearTimeout(el.data("timeout"));
          el.data("timeout", window.setTimeout(function() { el.find(".info").fadeOut("fast") }, 250));
        }
      );
    }
    
    function initImgHover() {
      $("img.hover").hover(
        function() { this.src = this.src.replace("-normal", "-hover") },
        function() { this.src = this.src.replace("-hover", "-normal") }
      );
    }
    
    function hideJobAd() {
      if (!visible) return;
      visible = false;
      fader.fadeOut(300);
      ad.animate({top: "-" + height + "px"}, 300, "swing", function() { body.trigger("activate-gallery"); toggleIcon.text("B").closest("a").attr("href", "#job"); ad.removeClass("visible"); });
    }
    
    function showJobAd() {
      if (visible) return;
      var top = Math.round((body.outerHeight() - height) / 2 - 30);
      if (top < 0) top = 10;
      visible = true;
      body.trigger("deactivate-gallery");
      fader.fadeTo(300, 0.5);
      ad.addClass("visible").fadeIn(100).animate({top:  top + "px"}, 300, "swing", function() { toggleIcon.text("A").closest("a").attr("href", "#");  });
    }
    
    initFader();
    ad.css({top: "-" + height + "px"});
    initPersonInfo();
    initImgHover();
    
    $(window).bind("resize", function() { 
      if (faderTimeout) window.clearTimeout(faderTimeout);
      faderTimeout = window.setTimeout(initFader, 50);
    });
    body.bind({"show-job-ad": showJobAd, "hide-job-ad": hideJobAd});
  }
  
  
  // IRB-Snippet zum Renamen der aus PS exportierten Bilder:
  // Dir.glob("*").sort.reverse.each_with_index{|f, i| FileUtils.mv(f, "#{i + 1}.jpg") }
  function createProjects(data) {
    var i = 1, projects = [];
    $.each(data, function() {
      for (i; i <= this[0]; i++) {
        var img = tmpl("_img/gallery/${i}.jpg", {i: i});
        projects.push(new Project(img, this.slice(1)));
      }
    });
    return projects;
  }
  
  
  
  function Project(img, data) {
    this.img            = img;
    this.title          = data[0];
    this.responsibility = data[1];
    this.technology     = data[2];
    this.year           = data[3];
    this.url            = "http://" + data[4];
    this.additionalInfo = data[5] || "";
  };
  Project.prototype = {
    getInfoboxContent: function() {
      return $("<section/>").
        append($("<h1/>").text(this.title)).
        append($("<p class='responsibility'/>").text(this.responsibility)).
        append($("<p class='additional-info'/>").text(this.additionalInfo)).
        append($("<p class='year-and-technology'/>").text(this.technology + " (" + this.year + ")"));
    }    
  };
  
  
  
  var Gallery = (function() {
    var config = {
      rows: 3, cols: 8, 
      gap: 1,
      imgPath: "_img/gallery", imgSize: 100,
      interval: 5000,
      infoBoxDelay: 500
    };  
    var root, numImages, projects, imageElements = [], clipElement, rootHover = false, infoBoxTimeout, infoBox, active = true;
    
    function makeAbsolute(el) {
      var pos = el.offset();
      el.css({position: "absolute", float: "none", zIndex: 10}).offset(pos);
    }
    
    function makeGalleryAbsolute() {
      var width = config.cols * (config.imgSize + config.gap),
          height = config.rows * (config.imgSize + config.gap);
      root.width(width).height(height)
        .css({position: "relative", clip: tmpl("rect(0 ${w}px ${h}px 0)", {w: width, h: height})});
    }
    
    function createInfobox() {
      infoBox = $("<div class='infobox'/>").width(config.imgSize * 2 + config.gap).height(config.imgSize).
        css({position: "absolute", "z-index": 15}).hide().appendTo(root);
    }
    
    function createImageElements() {
      for (var x = 0; x < config.cols; x++) {
        for (var y = 0; y < config.rows; y++) {
          var el = $("<img>").width(config.imgSize).height(config.imgSize).appendTo(root).wrap("<a>");
          imageElements.push(el);
        }
      }
      clipElement = $("<div>").hide()
        .css({position: "absolute", zIndex: 50, left: 0, top: 0, clip: tmpl("rect(0, ${size}px, ${size}px, 0)", {size: config.imgSize})})
        .width(2 * (config.imgSize + config.gap)).height(2 * (config.imgSize + config.gap))
        .appendTo(root);
    }
    
    function makeImageElementsAbsolute() {
      for (var i = imageElements.length - 1; i >= 0; i--) {
        makeAbsolute(imageElements[i]);
      }
    }
    
    function setImages() {
      shuffle(projects);
      for (var i = 0; i < imageElements.length; i++) {
        imageElements[i].attr("src", projects[i].img).data("project", projects[i]);
        imageElements[i].closest("a").attr("href", projects[i].url);
      }
      // shuffle used images again, otherwise images will be changed beginning from top left
      shuffle(projects, 0, imageElements.length);
    }
    
    function addHoverHandler() {
      root.hover(
        function() { if (active) rootHover = true  },
        function() { rootHover = false }
      );
      root.delegate("img", {
        mouseenter: function() { if (infoBoxTimeout) window.clearTimeout(infoBoxTimeout); if (active) infoBoxTimeout = window.setTimeout(showInfoBox, config.infoBoxDelay); },
        mouseleave: function() { hideInfoBox(); window.clearTimeout(infoBoxTimeout); }
      });
    }
    
    function showInfoBox() {
      var img       = root.find("img:hover");
      var imgPos    = img.position();
      var content   = img.data("project").getInfoboxContent();
      var offsets   = [[-1, -1], [0, -1], [1, 0], [0, 1], [-1, 1], [-2, 0]];
      var positions = [];
      var leftMax   = root.width() - infoBox.width();
      var topMax    = root.height() - infoBox.height();
      for (var i = 0; i < offsets.length; i++) {
        var left  = imgPos.left + offsets[i][0] * (config.imgSize + config.gap);
        var top   = imgPos.top  + offsets[i][1] * (config.imgSize + config.gap);
        if (left >= 0 && left <= leftMax && top >= 0 && top <= topMax) 
          positions.push({left: left + "px", top: top + "px"});
      }
      infoBox.html(content).css(positions[rand(positions.length)]).fadeIn(200);
      infoBox.toggleClass("right", infoBox.position().left < imgPos.left);
    }
    
    function hideInfoBox() {
      infoBox.fadeOut(200);
    }
    
    function changeImage() {
      if (!active || rootHover) return;
      var duration  = 500,
          firstProject = projects.shift(),
          newProject   = projects[imageElements.length - 1];
          origImgEl    = root.find(tmpl("[src='${first}']", {first: firstProject.img})),
          newImgEl     = $("<img>").attr("src", newProject.img).data("project", newProject);
          pos          = {position: "absolute", float: "none", margin: 0, left: origImgEl.position().left, top: origImgEl.position().top},
          completeCB   = function() {
            origImgEl.remove();
            newImgEl.css(pos).appendTo(root).wrap($("<a>").attr("href", newProject.url));
            clipElement.hide();
          };
      origImgEl.unwrap().css({position: "static", float: "left", left: 0, top: 0});
      switch (rand(4)) {
        case 0: // from right
          clipElement.css(pos).show().append(origImgEl, newImgEl);
          origImgEl.animate({marginLeft: -(config.imgSize + config.gap) + "px"}, duration, "easeInOutCubic", completeCB);
          break;
        case 1: // from left
          newImgEl.css({marginLeft: -(config.imgSize + config.gap) + "px"});
          clipElement.css(pos).show().append(newImgEl, origImgEl);
          newImgEl.animate({marginLeft: 0}, duration, "easeInOutCubic", completeCB);
          break;
        case 2: // from top
          newImgEl.css({marginTop: -(config.imgSize + config.gap) + "px", float: "none"});
          clipElement.css(pos).show().append(newImgEl, origImgEl);
          newImgEl.animate({marginTop: 0}, duration, "easeInOutCubic", completeCB);
          break;
        case 3: // from bottom
          origImgEl.css({float: "none"});
          clipElement.css(pos).show().append(origImgEl, newImgEl);
          origImgEl.animate({marginTop: -(config.imgSize + config.gap) + "px"}, duration, "easeInOutCubic", completeCB);
          break;

      }
      projects.push(firstProject);
    }
    
    function deactivate() {
      active = false;
    }
    
    function activate() {
      active = true;
    }
    
    return {
      init: function(_root, _projects) {
        root      = $(_root);
        projects  = _projects;
        numImages = _projects.length;
        makeGalleryAbsolute();
        createInfobox();
        createImageElements();
        makeImageElementsAbsolute();
        setImages();
        addHoverHandler();
        window.setInterval(changeImage, config.interval);
        $("body").bind({
          "activate-gallery": activate,
          "deactivate-gallery": deactivate
        });
      }
    };
  })();

  var project_data = [
    [ 3, "Sparkling Science",     "Design & Umsetzung", "2007–2011", "PHP/Ruby on Rails", "www.sparklingscience.at",          "Design mit Oliver Schöndorfer"],
    [ 7, "Projekt Querdenken",    "Design & Umsetzung", "2007/08",   "PHP",               "www.projekt-querdenken.eu"],
    [ 8, "Psychnet",              "Design & Umsetzung", "2011",      "Ruby on Rails",     "www.psychnet.at"],
    [11, "Martin Hesz",           "Design & Umsetzung", "2010",      "PHP",               "www.martinhesz.com"],
    [13, "KFZ-Innung NÖ",         "Design & Umsetzung", "2008",      "Ruby on Rails",     "www.kraftfahrzeugtechniker.at"],
    [16, "Schulhomepageaward",    "Design & Umsetzung", "2011",      "PHP",               "schulhomepageaward.bmukk.gv.at"],
    [17, "Virtuelle Schule.AT",   "Design & Umsetzung", "2009",      "Typo3",             "virtuelleschule.bmukk.gv.at"],
    [18, "deveco Consulting"    , "Design & Umsetzung", "2010",      "Typo3",             "www.deveco.at"],
    [20, "Netzwerke im Dialog",   "Design & Umsetzung", "2009",      "Typo3",             "www.netzwerke-im-dialog.at"],
    [22, "Taskforce BHC",         "Umsetzung",          "2008",      "Typo3",             "www.taskforcehumancapital.info",   "Design: PeterGregsonStudio"],
    [24, "Conceptfrucht",         "Umsetzung",          "2010",      "PHP",               "www.conceptfrucht.com",            "Design: Wolfgang Bledl"],
    [26, "Westside Soccer Arena", "Umsetzung",          "2011",      "Facebook",          "www.facebook.com/westsidesoccer",  "Design: Hubert Wedel"],
    [27, "XMAS 2010",             "Design & Umsetzung", "2010",      "JavaScript",        "www.die-antwort.eu/xmas/"],
    [29, "Beim Bruckner",         "Umsetzung",          "2010",      "PHP",               "www.beimbruckner.at",              "Design: Martin Hesz"],
    [31, "Feldenkrais Institut",  "Design & Umsetzung", "2007",      "PHP",               "www.feldenkraisinstitut.at"],
    [33, "harrison wineSelect",   "Umsetzung",          "2009",      "PHP",               "www.wineselect.at",                "Design: Alexandra Warlits"],
    [34, "My Bijoux",             "Umsetzung",          "2009",      "PHP",               "www.mybijoux.at",                  "Design: Martin Hesz"],
    [36, "Steinfeld",             "Umsetzung",          "2010",      "PHP",               "www.steinfeldwine.com",            "Design: Alexandra Warlits"]
  ];
  Gallery.init("#gallery", createProjects(project_data));
  
  initJobAd();
  $(window).hashchange(function() {
    if (location.hash == "#job") 
      $("body").trigger("show-job-ad");
    else
      $("body").trigger("hide-job-ad");
  });
  $(window).hashchange();
});
