// FIXME IE does not recognize the namespace, unless it is previously initiated
var fd = {image : { effects : {}, navigation : {}}};

(function(root){
  namespace(namespace);

  function namespace(namespace, functions) {
    if(typeof arguments[0] != "string"){
      return namespace_for_root.apply(this, arguments);
    }
    var parts = arguments[0].split("."),
        space = namespaceFor(parts);

    for (var i=1; i < arguments.length; i++) {
      space[functionName(arguments[i])] = arguments[i];
    }
  }

  function namespace_for_root(functions){
    for (var i=0; i < arguments.length; i++) {
      root[functionName(arguments[i])] = arguments[i];
    }
  }

  function functionName(fn) {
    return fn.name ? fn.name : fn.toString().match(/^\s*function\s+([^\s\(]+)/)[1];
  }

  function namespaceFor(parts) {
    var space = root;
    for (var i=0; i < parts.length; i++) {
      space = space[parts[i]] = space[parts[i]] || {};
    }
    return space;
  }

})(this); // <- change this if you want to change the scope of namespace

(function(){
  namespace("fd.image", view, style, start, images, addEffect);

  var _view, _style, _images; // where the image is displayed

  function view(v){
    if(v !== undefined){ _view = v; return fd.image;}
    return _view;
  }

  // Not used yet
  function style(v){
    if(v !== undefined){ _style = v; return fd.image;}
    return _style;
  }

  function images(v){
    if(v !== undefined){ _images = v; return fd.image;}
    return _images;
  }

  function start(callback){
    _images.find(".image").hide();
    _images.show();
    fd.image.navigation.init(_images);
    if(callback) {callback();}
    return fd.images;
  }

  function addEffect(fn){
    fn();
    return fd.image;
  }

})();

(function(){
  namespace("fd.image.effects", orient);

  var oriented_image;

  function orient(){
    $(".image img").css({visibility: "hidden"});
    $(window).resize(function(){
      var image = fd.image.navigation.selected();
      image.trigger("fd:image:show", image);});

    $(document.body).bind("fd:image:show", do_orient);
  }

  // TODO support iframes for video
  function do_orient(event, image){

    if($(image).find("img").length === 0) { return true;}

    if(!$(image).find("img")[0].complete){
      return setTimeout(function(){do_orient(event,image);}, 200);
    }

    var view        = fd.image.view(),
        img         = $(image).find("img").show(),
        width       = img.attr("width"),
        text_height = 20 + $(image).find(".caption").outerHeight(true) + view.find(".description").outerHeight(true),
        height      = img.attr("height"),
        image_r     = (width /(height)),
        view_r      = (view.outerWidth(true) /(view.height()-text_height)),
        o           = ["100%", "auto"],
        // use window height for an IE workaround
        view_height = Math.min($(window).height(), view.height());

    o = (image_r >= view_r) ? ["100%", "auto"] : ['auto', view_height - text_height];
    img.css({width:o[0], height:o[1], visibility: 'visible'});
  }
})();


(function(){
  namespace("fd.image.navigation", init, select, selected, next, prev, setClick);

  var visible, images, clickFunction;

  function init(imgs){
    images = imgs;
    if(images.find(".image").length > 1){
      images.find(".image").live("click", click);
    } else {
      images.find(".image").css("cursor","default");
    }

    $("#images_next").live("click", next);
    $("#images_previous").live("click", prev);

    select(0);
  }

  function setClick(fn){
    clickFunction = fn;
    return fd.image.navigation;
  }

  function selected(){
    return visible;
  }

  function select(index){
    var t = images.find(".image:eq("+index+")");
    if(t[0]){
      if(visible) {hide.apply(visible);}
      show.apply(t);
    }
  }

  function direction(d){
    if ($(this)[d]()[0] === undefined){
      var a = $(".collections li.selected")[d]().find("a")[0];
      if(a){
        document.location.href = a.href;
        return document.location.href;
      }
      $(this).fadeOut(100, function(){$(this).fadeIn();});
    } else {
      hide.apply(this);
      show.apply($(this)[d]());
    }
  }

  function which_direction(e){
    return (e.offsetX >= $(e.target).width()/2) ? "next" : "prev";
  }

  function next(){
    direction.apply(images.find(".image:visible")[0], ["next"]);
  }

  function prev(){
    direction.apply(images.find(".image:visible")[0], ["prev"]);
  }

  function click(e){
    var d = "next"
    if(clickFunction){ d = clickFunction(e); }
    direction.apply(this, [d]);
  }

  function show(){
    visible = this;
    $(this)
    .addClass("selected")
    .fadeIn(250)
    .trigger("fd:image:show", visible);
   }

  function hide(){
    if(this === undefined){ return false;}
    $(this).hide().removeClass("selected").trigger("fd:image:hide", this);
  }

})();

