$(function() {

  var gfHistory = window.History;
  var currentSection = "intro";
  var duration = 1000;
  var easing = "easeOutExpo";
  var speed = "medium";
  var sectionPaddingBottom = parseInt($(".section").css("paddingBottom"), 10);
  var scrollTopTimeout = null;
  var scrollTops = {};
  var scrollToTopDisable = false;
  var pAnimLock = true; // this gets unlocked after all featured portfolio entries are analyzed
  var pIndex = 0;
  var pThumbWidth = 150;
  var pCount = $("#portfolio .navigation .entries ul li").length;
  var pNavMarginLeft = function() { return ((pIndex * (0 - pThumbWidth)) - (pThumbWidth * 6))+"px"; };
  var pNextTimeout = null;
  var pNextDuration = 5000;
  var pfNextDuration = 10000;
  var pfCount = 0;
  var pfLength = $("#portfolio .featured").length;
  var resizeTimeout = null;

  var setScrollTops = function() {
    var contentPaddingTop = parseInt($("#content").css("paddingTop"), 10);
    $(".section").each(function() { scrollTops[$(this).attr("id")] = Math.round($(this).offset().top - contentPaddingTop); });
  };
  
  var adjustContactHeight = function() {
    if ($("#contact").data("originalHeight") === undefined) $("#contact").data("originalHeight", $("#contact").height());
    var originalHeight = $("#contact").data("originalHeight");
    var targetHeight = ($(window).height() - ($("#header").height() * 2)); // this ends up being 3 pixels too tall for some reason
    if (targetHeight > originalHeight) $("#contact").height(targetHeight);
  };

  var getCurrentURL = function() {
    var State = gfHistory.getState();
    var url = "";
    url = State ? State.url.replace(BASE_URL, "") : location.href.replace(MAIN_URL, "");
    if (url.substr((url.length - 1), 1) == "/") url = url.substr(0, (url.length - 1));  
    return url;
  };

  var stateChange = function() {
    var url = getCurrentURL();
    _gaq.push(['_trackPageview', '/'+url]);
    var sectionObj = parseSection(url);
    clearTimeout(scrollTopTimeout);
    navigateTo(sectionObj);
  };

  var parseSection = function(url) {
    var sectionParts = url.split("/");
    var sectionObj = {
      "name": (sectionParts.length && sectionParts[0]) ? sectionParts[0] : "intro",
      "more": ((sectionParts.length > 1) && (sectionParts[1] == "more")),
      "entry": ((sectionParts.length > 1) && (sectionParts[1] != "more") && (sectionParts[1] != "previous") && (sectionParts[1] != "next")) ? sectionParts[1] : null
    };
    if (sectionObj.entry && (sectionParts.length > 2) && (sectionParts[2] == "more")) sectionObj.more = true;
    return sectionObj;
  };

  var setSection = function(sectionObj) {
    currentSection = sectionObj.name;
    $("#navigation ul li").removeClass("selected");
    $("#navigation ul li a").each(
      function() {
        var href = $(this).attr("href").replace(MAIN_URL, "");
        href = href.substr(0, (href.length - 1));
        if (href == sectionObj.name) $(this).parent().addClass("selected");
      });
  };

  var navigateTo = function(sectionObj, animate) {
    if (sectionObj && sectionObj.name && $("#"+sectionObj.name).length) {
      more = (typeof(sectionObj.more) == "undefined") ? false : sectionObj.more;
      entry = (typeof(sectionObj.entry) == "undefined") ? null : sectionObj.entry;
      animate = (typeof(animate) == "undefined") ? true : animate;
      if (sectionObj.name != "portfolio") {
        if (sectionObj.more && !$("#"+sectionObj.name).hasClass("more")) {
          learnMore(sectionObj, false);
        } else if (!more && $("#"+sectionObj.name).hasClass("more")) {
          showLess(sectionObj, false);
        }
      }
      if (!scrollToTopDisable) scrollToTop(sectionObj.name, animate);
      scrollToTopDisable = false;
      setSection(sectionObj);
      if (sectionObj.name == "portfolio") portfolioSection(sectionObj, animate);
      else clearTimeout(pNextTimeout);
    }
  };

  var scrollToTop = function(sectionName, animate) {
    var scrollTop = scrollTops[sectionName];
    animate = (typeof(animate) == "undefined") ? true : animate;
    if (animate) {
      $("html,body").animate({scrollTop: scrollTop}, duration, easing);
    } else {
      $('html,body').scrollTop(scrollTop);
    }
  };
  
  var stripChars = function(str) {
    str = str.replace(/ & /g, " and ");
    str = str.replace(/ /g, "-");
    str = str.replace(/\./g, "-");
    str = str.replace(/[^a-zA-Z0-9\-]/g, "");
    return str;
  };
  
  var learnMore = function(sectionObj, animate) {
    animate = (typeof(animate) == "undefined") ? true : animate;
    if (animate) navigateTo(sectionObj);
    $("#"+sectionObj.name).addClass("more");
    if ($("#"+sectionObj.name+" .learn-more a").length) {
      $("#"+sectionObj.name+" .learn-more a")
        .attr("href", $("#"+sectionObj.name+" .learn-more a").attr("href").replace("more/", ""))
        .text("Show less");
    }
    if (sectionObj.name == "about") {
      $("#about .header").addClass("expanded");
      $("#about .expanded").show();
      $("#about .technologies").show();
    } else if (sectionObj.name == "clients") {
      $("#clients .testimonials dl dd:not(.expanded)").hide();
      $("#clients .testimonials dl dd.expanded").show();
      $("#clients .clients .text-list").show();
    } else if (sectionObj.name == "nimba-cms") {
      $("#nimba-cms .collapsed").hide();
      $("#nimba-cms .expanded").show();
    }
    setScrollTops();
  };

  var showLess = function(sectionObj, animate) {
    animate = (typeof(animate) == "undefined") ? true : animate;
    if (animate) navigateTo(sectionObj);
    $("#"+sectionObj.name).removeClass("more");
    if ($("#"+sectionObj.name+" .learn-more a").length) {
      $("#"+sectionObj.name+" .learn-more a")
        .attr("href", $("#"+sectionObj.name+" .learn-more a").attr("href").replace("more/", "")+"more/")
        .text("Learn more");
    }
    if (sectionObj.name == "about") {
      $("#about .header").removeClass("expanded");
      $("#about .expanded").hide();
      $("#about .technologies").hide();
    } else if (sectionObj.name == "clients") {
      $("#clients .testimonials dl dd.expanded").hide();
      $("#clients .testimonials dl dd:not(.expanded)").show();
      $("#clients .clients .text-list").hide();
    } else if (sectionObj.name == "nimba-cms") {
      $("#nimba-cms .collapsed").show();
      $("#nimba-cms .expanded").hide();
    }
    setScrollTops();
  };

  var getPortfolioSection = function() {
    sectionObj = {name: "portfolio"};
    if ($("#portfolio .detail:visible").length) {
      sectionObj.entry = $("#portfolio .detail:visible").attr("id").substr(7);
      sectionObj.more = $("#portfolio .detail:visible").hasClass("more");
    }
    return sectionObj;
  };

  var portfolioNavigate = function(previous, next) {
    if (pCount >= 18) {
      var pCountActual = (pCount - 12);
      pIndex += next ? 1 : -1;
      $("#portfolio .navigation ul")
        .stop()
        .animate({"margin-left": pNavMarginLeft()}, duration, easing,
          function() {
            var oldPIndex = pIndex;
            if (pIndex <= -6) pIndex = (pCountActual + pIndex);
            if (pIndex >= pCountActual) pIndex = (pIndex - pCountActual);
            if (pIndex != oldPIndex) $(this).css("margin-left", pNavMarginLeft());
          });
    }
  };

  var enablePortfolioSlideshow = function(initialDelay) {
    // this function is used to animate through featured entries or portfolio entry images
    initialDelay = (typeof(initialDelay) == "undefined") ? false : initialDelay;
    var portfolioObj = null;
    var nextDuration = null;
    if ($("#portfolio .featured:visible").length && $("#portfolio .featured:visible .image-nav").length) {
      portfolioObj = $("#portfolio .featured:visible");
      nextDuration = pfNextDuration;
    } else if ($("#portfolio .detail:visible").length && $("#portfolio .detail:visible .image-nav").length) {
      portfolioObj = $("#portfolio .detail:visible");
      nextDuration = pNextDuration;
    }
    if (portfolioObj) {
      var setNextTo = function() {
        clearTimeout(pNextTimeout);
        pNextTimeout = setTimeout(function() {
          if ($(portfolioObj).find(".image-nav .selected").length) {
            var inl = $(portfolioObj).find(".image-nav li").length;
            var ini = $(portfolioObj).find(".image-nav .selected").index();
            ini++;
            if (ini >= inl) ini = 0;
            var url = $(portfolioObj).find(".image-nav li:eq("+ini+") a").attr("href").replace(MAIN_URL, "");
            if ($(portfolioObj).hasClass("featured")) {
              portfolioFeatured(url.substr(11, (url.length - 12)));
            } else if ($(portfolioObj).hasClass("detail")) {
              portfolioImage(url.substr(8, (url.length - 9)));
            }
          }
        }, nextDuration);
      };
      if (initialDelay) {
        clearTimeout(pNextTimeout);
        pNextTimeout = setTimeout(setNextTo, (nextDuration / 2));
      } else {
        setNextTo();
      }
    }
  };

  var portfolioFeatured = function(pKey, initialDelay) {
    initialDelay = (typeof(initialDelay) == "undefined") ? false : initialDelay;
    if (pAnimLock) {
      setTimeout(function() { portfolioFeatured(pKey, initialDelay); }, 250);
      return;
    }
    var pfCurrent = $("#portfolio .featured:visible");
    if ($(pfCurrent).length == 1) {
      var pfCurrentKey = $(pfCurrent).data("key");
      if (pfCurrentKey != pKey) {
        pAnimLock = true;
        clearTimeout(pNextTimeout);
        var pfCurrentHeight = $("#portfolio .featured:data('key="+pfCurrentKey+"')").data("height");
        var pfNext = $("#portfolio .featured:data('key="+pKey+"')");
        var pfNextHeight = $(pfNext).data("height");
        $("#portfolio .entry").height(pfCurrentHeight);
        $(pfCurrent).fadeOut(speed, function() {
          var pfAfterAnimHeight = function() {
            $(pfNext).fadeIn(speed, function() {
              setScrollTops();
              enablePortfolioSlideshow(initialDelay);
              pAnimLock = false;
            });
          };
          if (pfCurrentHeight != pfNextHeight) {
            $("#portfolio .entry").animate({height: pfNextHeight+"px"}, speed, function() { pfAfterAnimHeight(); });
          } else {
            pfAfterAnimHeight();
          }
        });
      }
    }
  };

  var portfolioImage = function(imageIndex, initialDelay) {
    initialDelay = (typeof(initialDelay) == "undefined") ? false : initialDelay;
    if ($("#portfolio .detail:visible").length) {
      imageIndex--; // the index is 1-based, not zero-based, so decrement it
      clearTimeout(pNextTimeout);
      $("#portfolio .detail:visible .image-nav ul li").removeClass("selected");
      $("#portfolio .detail:visible .image-nav ul li:eq("+imageIndex+")").addClass("selected"); 
      $("#portfolio .detail:visible .images ul li").each(function() {
        if (($(this).index() == imageIndex) && ($(this).css("opacity") != 1)) $(this).stop().fadeTo(speed, 1);
        else if ($(this).index() != imageIndex && ($(this).css("opacity") != 0)) $(this).stop().fadeTo(speed, 0);
      });
      setTimeout(function() { enablePortfolioSlideshow(initialDelay); }, 200);
    }
  };

  var portfolioSection = function(sectionObj, animate) {
    animate = (typeof(animate) == "undefined") ? true : animate;
    if (pAnimLock) {
      setTimeout(function() { portfolioSection(sectionObj, animate); }, 250);
      return;
    }
    var visibleDivFadeLock = true;
    var showPortfolio = function(sectionObj, animate) {
      if (visibleDivFadeLock) {
        setTimeout(function() { showPortfolio(sectionObj, animate); }, 250);
        return;
      }
      if (sectionObj.entry) {
        if (sectionObj.more) {
          $("#detail-"+sectionObj.entry).addClass("more");
          $("#detail-"+sectionObj.entry+" .collapsed").hide();
          $("#detail-"+sectionObj.entry+" .expanded").show();
          $("#detail-"+sectionObj.entry+" .learn-more a").hide();
        } else {
          $("#detail-"+sectionObj.entry).removeClass("more");
          $("#detail-"+sectionObj.entry+" .collapsed").show();
          $("#detail-"+sectionObj.entry+" .expanded").hide();
          $("#detail-"+sectionObj.entry+" .learn-more a").show();
        }
      }
      $("#portfolio .navigation .entries ul li a").each(function() {
        var i = $(this).find(".gradient");
        if (sectionObj.entry && $(this).parent().hasClass($("#detail-"+sectionObj.entry).data("key"))) {
          $(this).parent().addClass("selected");
          $(i).attr("src", $(i).attr("src").replace("other-bg", "other-hover-bg"));
        } else {
          $(this).parent().removeClass("selected");
          $(i).attr("src", $(i).attr("src").replace("other-hover-bg", "other-bg"));
        }
      });
      var divSelector = sectionObj.entry ? "#detail-"+sectionObj.entry : "#portfolio .featured-entries";
      $("#portfolio .entry").removeClass("loading");
      if (animate) {
        $(divSelector).fadeIn(speed);
      } else {
        $(divSelector).show();
      }
      $(divSelector).evenIfHidden(function(e) {
        var pdHeight = $(e).height();
        var pdAfterAnimHeight = function() {
          $("#portfolio .entry")
            .css("overflow", "visible")
            .height("auto");
          setScrollTops();
          if (currentSection != "portfolio") scrollToTop(currentSection);
          enablePortfolioSlideshow(true);
          pAnimLock = false;
        };
        if ($("#portfolio .entry").height() != pdHeight) {
          if (animate) {
            $("#portfolio .entry").animate({height: pdHeight+"px"}, speed, function() { pdAfterAnimHeight(); });
          } else {
            $("#portfolio .entry").height(pdHeight);
            pdAfterAnimHeight();
          }
        } else {
          pdAfterAnimHeight();
        }
      });
    };
    clearTimeout(pNextTimeout);
    if (($("#portfolio .featured-entries:visible").length && sectionObj.entry) ||
        (sectionObj.entry && (($("#portfolio .detail:visible").data("key") != sectionObj.entry) ||
                              ($("#portfolio .detail:visible").hasClass("more") && !sectionObj.more) ||
                              (!$("#portfolio .detail:visible").hasClass("more") && sectionObj.more))) ||
        (!$("#portfolio .featured-entries:visible").length && !sectionObj.entry)) {
      pAnimLock = true;
      scrollToTop("portfolio");
      if (sectionObj.entry && !$("#detail-"+sectionObj.entry).length) {
        var detailDiv = $("<div></div>")
                          .addClass("detail")
                          .attr("id", "detail-"+sectionObj.entry)
                          .hide()
                          .data("key", sectionObj.entry);
        $("#portfolio .entry").append(detailDiv);
        Global.loadAction("#detail-"+sectionObj.entry, "PortfolioDetail", {portfolio_key: sectionObj.entry}, function() {
          $("#detail-"+sectionObj.entry+" .collapsed, #detail-"+sectionObj.entry+" .expanded").evenIfHidden(function(e) { $(e).data("height", $(e).height()); });
          showPortfolio(sectionObj, animate);
        });
      } else {
        showPortfolio(sectionObj, animate);
      }
      $("#portfolio .entry")
        .height($("#portfolio .entry").height())
        .css("overflow", "hidden");
      var visibleDiv = null;
      if ($("#portfolio .featured-entries:visible").length) visibleDiv = $("#portfolio .featured-entries:visible");
      else if ($("#portfolio .detail:visible").length) visibleDiv = $("#portfolio .detail:visible");
      if (visibleDiv) {
        var pdAfterFadeVisible = function() {
          $(visibleDiv).hide();
          $("#portfolio .entry").addClass("loading");
          visibleDivFadeLock = false;
        };
        if (animate) {
          $(visibleDiv).fadeOut(speed, pdAfterFadeVisible);
        } else {
          pdAfterFadeVisible();
        }
      } else {
        visibleDivFadeLock = false;
      }
    } else {
      enablePortfolioSlideshow(true);
    }
  };



  // Global initialization

  var init = function() {
    adjustContactHeight();
    setScrollTops();
  };
  init();
  $(window)
    .load(function() { init(); })
    .resize(function() {
      clearTimeout(resizeTimeout);
      resizeTimeout = setTimeout(function() { init(); }, 500);
    });

  if (typeof JSON === "undefined") {
    var url = URL_PREFIX_JS+"history/json2.js";
    var scriptEl = document.createElement("script");
    scriptEl.type = "text/javascript";
    scriptEl.src = url;
    document.body.appendChild(scriptEl);
  }

  gfHistory.Adapter.bind(window, "statechange", function() { stateChange(); });
  stateChange();

  $(window).bind('mousewheel', function() { $("html,body").stop(); });

  $(window).scroll(function(e) {
    if (!pAnimLock) {
      clearTimeout(scrollTopTimeout);
      scrollTopTimeout = setTimeout(function() {
        var scrollTop = $(window).scrollTop();
        var newSection = null;
        var lastSection = null;
        for (var i in scrollTops) {
          if (scrollTop >= (scrollTops[i] - sectionPaddingBottom)) newSection = i;
          lastSection = i;
        }
        if ((scrollTop + $(window).height()) >= ($("body").height() - 100)) newSection = lastSection;
        if (newSection && (newSection != currentSection) && $("#"+newSection).length) {
          var url = (newSection != "intro") ? "/"+newSection : "";
          if (newSection == "portfolio") {
            if ($("#portfolio .detail:visible").length) {
              url += "/"+$("#portfolio .detail:visible").data("key");
              if ($("#portfolio .detail:visible").hasClass("more")) url += "/more";
            }
          } else if ($("#"+newSection).hasClass("more")) {
            url += "/more";
          }
          scrollToTopDisable = true;
          gfHistory.pushState(null, null, url+"/");
        }
      }, 250);
    }
  });

  $("a:not(.view-site)").live("click", function() {
    if ($(this).attr("href").indexOf(MAIN_URL) == 0) {
      var url = $(this).attr("href").replace(MAIN_URL, "");
      if (url.substr((url.length - 1), 1) == "/") url = url.substr(0, (url.length - 1));  
      if (url.substr(0, 2) == "#/") {
        if (currentSection != "portfolio") {
          var sectionObj = getPortfolioSection();
          var portfolioURL = "/"+sectionObj.name+"/";
          if (sectionObj.entry) portfolioURL += sectionObj.entry+"/";
          if (sectionObj.more) portfolioURL += "more/";
          gfHistory.pushState(null, null, portfolioURL);
        }
        if ((url == "#/next") || (url == "#/previous")) {
          var nextPrevious = url.substr(2, (url.length - 2));
          portfolioNavigate((nextPrevious == "previous"), (nextPrevious == "next"));
        } else if (url.substr(2, 8) == "featured") {
          portfolioFeatured(url.substr(11), true);
        } else if (url.substr(2, 5) == "image") {
          portfolioImage(url.substr(8), true);
        }
      } else if (url != getCurrentURL()) {
        url = url ? (url + "/") : "";
        gfHistory.pushState(null, null, "/"+url);
      } else {
        scrollToTop(currentSection);
      }
      return false;
    }
  });



  // Section initialization

  $("#portfolio .navigation .entries ul").width(pCount * pThumbWidth);
  $("<img/>").attr("src", $("#portfolio .navigation .entries ul li a:first .gradient").attr("src").replace("other-bg", "other-hover-bg"));

  // delay loading of certain images 
  var delayImage = function() { $(this).data("src", $(this).attr("src")).attr("src", URL_PREFIX_IMAGE+"transparent.gif"); };
  var loadImage = function() { $(this).attr("src", $(this).data("src")); };
  $("#portfolio .navigation .entries ul li:not(.primary) a img:not(.gradient)").each(delayImage);
  $("#about .technologies ul li a img").each(delayImage);
  $("#nimba-cms .info .images .expanded ul li img").each(delayImage);
  $(window).load(function() {
    $("#portfolio .navigation .entries ul li:not(.primary) a img.logo").each(loadImage);
    $("#portfolio .navigation .entries ul li:not(.primary) a img.image").each(loadImage);
    $("#about .technologies ul li a img").each(loadImage);
    $("#nimba-cms .info .images .expanded ul li img").each(loadImage);
  });

  $("#portfolio .navigation .entries ul li a").hover(function() {
    var i = $(this).find(".gradient");
    $(i).attr("src", $(i).attr("src").replace("other-bg", "other-hover-bg"));
  }, function() {
    var i = $(this).find(".gradient");
    if (!$(this).parent().hasClass("selected")) $(i).attr("src", $(i).attr("src").replace("other-hover-bg", "other-bg"));
  });

  $("#portfolio .featured").each(function() {
    var fObj = this;
    var fKey = stripChars($(this).find("h3").text()).toLowerCase();
    $(fObj).data("key", fKey);
    $(fObj).evenIfHidden(function(e) {
      $(fObj).data("height", e.height());
      pfCount++;
      if (pfCount == pfLength) pAnimLock = false;
    });
  });

  var contactVars = ["name", "email", "message"];
  var contactValues = ["Full name", "Email address", "Message"];
  $.each(contactVars, function(i, v) {
    if (($("#contact_"+v).val() == "") || ($("#contact_"+v).val() == contactValues[i])) {
      $("#contact_"+v)
        .addClass("hint")
        .val(contactValues[i])
        .focus(function() { if ($(this).hasClass("hint")) $(this).val("").removeClass("hint"); })
        .blur(function() {
          if ($(this).val() == "") {
            var varName = $(this).attr("id").substr(8);
            var value = "";
            $.each(contactVars, function(i, v) { if (varName == v) value = contactValues[i]; });
            $(this).val(value).addClass("hint");
          }
        });
    }
  });
  $("#contact .form").css("min-height", $("#contact .form").height()); // set the min height because the form will be hidden after submission
  $("#contact_form .submit a").click(function() {
    var contactSubmitError = function(errorsExist) {
      $.each(contactVars, function(i, v) { $("#contact_"+v).focus().blur(); }); // reset the hint values
      if (!errorsExist) Validation.displayActionMessage("Contact", null, "There was an error submitting your request. Please try again.", "E", "");
    };
    $("#contact_form .hint").each(function() { $(this).val("").removeClass("hint"); });
    // TODO: adjust this handling for smoother submits
    Global.ajaxSubmitJSON("contact_form",
      function(data) {
        if (data.request.submit == "submit") {
          $("#contact .form p, #contact .form .form_content").hide();
          setTimeout(function() {
            $.each(contactVars, function(i, v) { $("#contact_"+v).val("").focus().blur(); });
            $("#contact .form .alert").hide();
            $("#contact .form p, #contact .form .form_content").fadeIn();
          }, 30000);
        } else {
          contactSubmitError();
        }
      },
      function(data) {
        var errorsExist = false;
        for (var i in data) errorsExist = true;
        contactSubmitError(errorsExist);
      }
    );
    return false; 
  });
});

