var CaseStudyManager = (function () {
  var instances = {};
  var sliding = false;
  var timer = null;

  var root;

  function CaseStudy(name, logo$, content$) {
    var self = this;
  
    self.content$ = content$;
    self.logo$ = logo$;
    self.name = name;
  
    function enableCurrent() {
      logo$.addClassName("current");
      content$.addClassName("current");    
    }
  
    function disableCurrent() {
      logo$.removeClassName("current");
      content$.removeClassName("current");
    }
  
    self.setCurrent = function (value) {
      if (value)
        enableCurrent();
      else
        disableCurrent();
    };
  
    self.getX = function () {
      return content$.positionedOffset()[0];
    };
  
    self.distanceTo = function (other) {
      return self.getX() - other.getX();
    };
  }

  function getNew(name) {
    var logo$ = $("client-" + name);
    var content$ = $("case-study-" + name);
    var result = new CaseStudy(name, logo$, content$);

    instances[name] = result;

    return result;
  }

  function get(name) {
    return instances[name] || getNew(name);
  }

  function parseID(name) {
    return name.replace(/^client-|^case-study-/, "");
  }

  function allContentElements() {
    return new Selector(".case-study").findElements(root);
  }
  
  function each(callback) {
    allContentElements().each(function (element) {
      callback(get(parseID(element.id)));
    });
  }

  function forward() {
    if (hasNext())
      slideTo(getNext());
  }

  function backward() {
    if (hasPrevious())
      slideTo(getPrevious());
  }

  function getNext() {
    return getByContentElement(getCurrent().content$.next());
  }

  function hasNext() {
    return getNext() != null;
  }

  function getPrevious() {
    return getByContentElement(getCurrent().content$.previous());
  }

  function hasPrevious() {
    return getPrevious() != null;
  }

  function getByContentElement(element) {
    return element == null ? null
      : get(parseID(element.id));
  }

  function isCurrent(value) {
    return value === getCurrent();
  }

  function getCurrent() {
    return get(parseID($$("#case-study-container .current")[0].id));
  }

  function slideTo(next) {
    if (!sliding && !isCurrent(next))
      performSlideTo(next);
  }

  function performSlideTo(next) {
    var previous = getCurrent();

    sliding = true;

    new Effect.Fade(previous.content$, {
      from: 1, to: 0.05, duration: 0.5
    });

    new Effect.Move($("case-study-wrapper"), {
      x: previous.distanceTo(next), y: 0, mode: "relative",
      transition: Effect.Transitions.sinoidal,

      beforeStart: function () {
        previous.setCurrent(false);
        next.setCurrent(true);
      },

      afterFinish: function () {
        previous.content$.setOpacity(1);
        sliding = false;

        if (timer !== null && !hasNext())
          stop();
      }
    });
  }

  function start() {
    timer = setInterval(forward, 6000);
  }

  function stop() {
    clearInterval(timer);
    timer = null;
  }

  function setCurrent(current) {
    each(function (study) {
      study.setCurrent(false);
    });

    current.setCurrent(true);
  };

  function show(next) {
    // Effect.ScrollTo(root);
    slideTo(next);
  }

  document.observe("dom:loaded", function () {
    root = $("case-studies-container");

    each(function (study) {
      study.logo$.down("a").observe("click", function (event) {
        show(study);
        event.currentTarget.blur();
        event.stop();
      });
    });

    root.observe("mousemove", function () {
      stop();
      Event.stopObserving(root, "mousemove");
    });

    document.observe("keydown", function (event) {
      if (event.keyCode == 37)
        backward();
      else if (event.keyCode == 39)
        forward();
    });

    if (location.hash === "") {
      // start();          
    } else {
      setCurrent(get(parseID(location.hash.substring(1))));
    }
  });

  return {
    show: function (name) {
      show(get(name));
      Effect.ScrollTo(root);
    }
  };
})();
