
function Loader(){
  this.show = function(){
    $("#loader").show();
  }
  this.hide = function(){
    $("#loader").hide();
  }
}
function HistoryApi(){
  var $this = this,
    isHTML5;

  this.hasHTML5Support = function(){
    if(isHTML5 !== undefined){
      return isHTML5;
    } else {
      return isHTML5 = !!(window.history && history.pushState);
    }
  }

  this.changeUrl = function(url){
    if(this.hasHTML5Support()){
      history.pushState({}, "", url);
    } else {
      $.address.value(url);
    }
  }

  this.registerOnChange = function(){
    if(this.hasHTML5Support()){
      window.onpopstate = function(event){
        loadUrl(document.location.pathname);
      }
    } else {
      var firstRun = true;
      $.address.change(function(event){
        var href = event.path;
        if($.address.baseURL()+"/" != homepage){
          document.location = homepage+"#"+document.location.pathname;
          return;
        }
        if(href == "/" && firstRun){
          // do not load anything - main page is always loaded first
          firstRun = false;
          return;
        }
        firstRun = false;

        loadUrl(href);
      });
    }
  }

  this.registerForms = function(){
    $("form.local").live("submit", function(event){
      event.preventDefault();
      var $form = $(this),
        invalid = false;
      $(".required", $form).each(function(){
        $this = $(this);
        if($this.val() == ""){
          highlightRequired($this);
          invalid = true;
        }
      });
      $('input.required[name^="hinter_"]', $form).each(function(){
        $this = $(this);
          highlightRequired($this);
          invalid = true;
      });
      if(invalid){
        return;
      }
      $.ajax({
        type: "post",
        dataType: "json",
        url: $form.attr("action"),
        data: $form.serialize(),
        success: function(data, textStatus, XMLHttpRequest){
          if(data.url != undefined){
            History.changeUrl(data.url);
            if(data.redirect != undefined){
              loadUrl(data.url);
              return;
            }
          }
          updatePage(data);
        },
        error: function(XMLHttpRequest, textStatus, errorThrown){
          data = {};
          try {
            data = $.parseJSON(XMLHttpRequest.responseText);
          } catch(error){
            data.content = XMLHttpRequest.responseText;
          }
          updatePage(data);
        },
        beforeSend: function(XMLHttpRequest){
          loader.show();
        },
        complete: function(XMLHttpRequest, textStatus){
          loader.hide();
        }
      });
    });
  }

  this.registerClick = function(){
    if(this.hasHTML5Support()){
      $("a.local").live("click", function(event){
        event.preventDefault();
        href = $(this).attr("href");

        if(href != document.location.pathname){
          history.pushState({}, "", href);
        }
        loadUrl(href);
      });
    } else {
      $("a.local").address(function(){
        href = $(this).attr("href");
        if(href == $.address.value()){
          $.address.update();
        }
        else {
          return href.replace(homepage, "");
        }
      });
    }
  }

  this.initialize = function(){
    if(this.hasHTML5Support() && $.address.value() != "/"){
      document.location = $.address.value();
    }
    this.registerForms();
    this.registerOnChange();
    this.registerClick();
  }

  this.initialize();
}

var Cache = function(options){
  this.settings = $.extend({
    maxSize: 50,
    lifetime: 300
  }, options);
  var settings = this.settings;

  var data = {};
  var size = 0;

  // Creating our own shift function because associative keys in js sucks
  var shift = function(obj){
    for(i in obj){
      value = data[i];
      delete data[i];
      return value;
    }
  }

  this.add = function(key, value){
    // If cache is full, remove first value
    if(size >= settings.maxSize){
      shift(data);
      size--;
    } else if(!data[key]){
      size++;
    }
    // Add the value at the end of array
    return data[key] = {
      expiresAt: new Date().getTime() + (settings.lifetime * 1000),
      value: value
    }
  }

  this.get = function(key){
    if(data[key] && data[key].expiresAt < new Date().getTime()){
      // cache expired
      delete data[key];
      size--;
      return undefined;
    }

    return data[key];
  }
}

var Slider = function(){
  var object = this,
    timer,
    last,
    $images,
    $slideshow,
    $buttons,
    $buttonsContainer,
    lock = false,
    duration = 400; // "normal"
  this.manualChange = function(index){
    object.stop();
    changeSlide(index);
  };
  this.next = function(){
    changeSlide();
  };
  this.start = function(){
    timer = setTimeout(object.next, 4000);
  };
  this.stop = function(){
    clearTimeout(timer);
  };
  this.initialize = function(){
    object.stop();
    $slideshow = $("#slider div.slider-slideshow");
    $images = $("img", $slideshow);
    $buttonsContainer = $("#slider-buttons");
    addButtons();
    $buttons = $("span", $buttonsContainer);
    $buttons.click(function(){
      $this = $(this);
      if($this.hasClass("active")){
        return;
      }
      object.manualChange($this.attr("index"));
    });
    $("img:not(.active)", $slideshow).each(function(){
      src = $(this).attr("src");
      $('<img />').attr("src", src);
    });
    if($images.length > 1){
      object.start();
    }
  };
  function addButtons(){
    $images.each(function(index){
      $this = $(this);
      $span = $("<span/>").attr("index", index).css("opacity", 0.5);
      $buttonsContainer.prepend($span);
      last = index;
      if(index == 0){
        $this.addClass("active");
        $span.addClass("active");
      }
    });
  }
  var changeSlide = function(next){
    if(lock){
      return;
    }
    lock = true;
    if(next == undefined){
      next = $("img.active", $slideshow).index() + 1;
    }
    if(next > last){
      next = 0;
    }
    $("span.active", $buttonsContainer).removeClass("active");
    $("span[index="+next+"]", $buttonsContainer).addClass("active");
    $currentImg = $("img.active", $slideshow);
    $nextImg = $("img:eq("+next+")", $slideshow);
    if(next > $currentImg.index()){
      $nextImg.fadeIn(duration, function(){
        $currentImg.hide(0, function(){
          lock = false;
          object.start();
        }).removeClass("active");
      }).addClass("active");
    } else {
      $nextImg.show(0, function(){
        $currentImg.fadeOut(duration, function(){
          lock = false;
          object.start();
        }).removeClass("active");
      }).addClass("active");
    }
  }
}

var SliderHome = function(){
  var object = this,
    timer,
    $images,
    $slideshow,
    lock = false,
    duration = 400; // "normal"
  this.next = function(){
    changeSlide();
  };
  this.start = function(delay){
    if(delay == undefined) delay = 0;
//    console.log("starting");
    timer = setTimeout(object.next, 4500 + delay);
  };
  this.stop = function(){
    clearTimeout(timer);
  };
  this.initialize = function(id, delay){
//    console.log("init");
    this.stop();
    $slideshow = $("#"+id+" div.slider-home-slideshow");
    $images = $("img", $slideshow);

//      $slideshow = $("div.slider-home-slideshow");
//      console.log("$slideshows[index]:");
//      console.log($slideshows[index]);
//      $images = $("img", $slideshow);

    if($images.length > 1){
      object.start(delay);
    }
  };
  var changeSlide = function(){
//    console.log("trying to change..");
    if(lock){
//      console.log("locked");
      return;
    }
    lock = true;
    next = $("img.active", $slideshow).index() + 1;
    if(next <= 0){
      $("img:eq(0)", $slideshow).addClass("active");
      next += 1;
//      console.log("active was < 0");
    }
    if(next >= $images.length){
//      console.log("next = 0");
      next = 0;
    }
//    console.log("next: "+next);
//    console.log("$images.length: "+$images.length);
//    console.log("next: "+next);
    $currentImg = $("img.active", $slideshow);
    $nextImg = $("img:eq("+next+")", $slideshow);
    if(next > $currentImg.index()){
      $nextImg.fadeIn(duration, function(){
        $currentImg.hide(0, function(){
//          console.log("done!");
          $currentImg.removeClass("active");
          $nextImg.addClass("active");
          lock = false;
          object.start();
        });
      });
    } else {
      $nextImg.show(0, function(){
        $currentImg.fadeOut(duration, function(){
//          console.log("done!");
          $currentImg.removeClass("active");
          $nextImg.addClass("active");
          lock = false;
          object.start();
        });
      });
    }

//    if(lock){
//      return;
//    }
//    lock = true;
//    next = $("img:visible", $slideshow).index() + 1;
////    console.log("next img: "+next);
//    if(next >= $images.length){
//      next = 0;
//    }
//    $currentImg = $("img:visible", $slideshow);
////console.log("$currentImg:");
////console.log($currentImg);
//    $nextImg = $("img:eq("+next+")", $slideshows);
////console.log("$nextImg:");
////console.log($nextImg);
//    if(next > $currentImg.index()){
//      $nextImg.fadeIn(duration, function(){
//        $currentImg.hide(0, function(){
//          lock = false;
//          object.start();
//        });
//      });
//    } else {
//      $nextImg.show(0, function(){
//        $currentImg.fadeOut(duration, function(){
//          lock = false;
//          object.start();
//        });
//      });
//    }
  }
}



var SliderHomeOld = function(){
  var object = this,
    timers = [],
//    lastIndexes = [],
    $images = [],
    $slideshows = [],
    locks = [],
    duration = 400; // "normal"
//    if(index != undefined)
//      changeSlide(index);
//    else
//      for(i in timers){
//        changeSlide(i);
//      }
  this.start = function(index){
    this.stop(index);
//    changeSlide(index);
    timers[index] = setInterval(function(){
      changeSlide(index);
    });
  };
  this.next = function(index){
    console.log("starting: "+index);
//    if(index != undefined)
    timers[index] = setTimeout(function(){changeSlide(index)}, 4500);
//    else{
//      delay = 0;
//      for(i in timers){
//        timer[i] = setTimeout(object.next(i), delay += 1500);
//      }
//    }
  };
  this.stop = function(index){
    if(index != undefined){
      console.log("stop: "+index);
//      clearTimeout(timers[index]);
      clearInterval(timers[index]);
    } else {
      console.log("stop all");
      for(i in timers){
        console.log("stopping: "+i);
//        timers = [];
//        clearTimeout(timers[i]);
        clearInterval(timers[i]);
      }
    }
  };
  this.initialize = function($objects){
    console.log("init");
    object.stop();
//    object.reset();

    $objects.each(function(index){
//      console.log(this);
//      console.log("index: "+index);
      $slideshows[index] = $("div.slider-home-slideshow", this);
//      console.log("$slideshows[index]:");
//      console.log($slideshows[index]);
      $images[index] = $("img", $slideshows[index]);
//      console.log("$images[index]:");
//      console.log($images[index]);
      locks[index] = false;
    });
//    $slideshow = $("div.slider-home-slideshow", $object);
//    $images = $("img", $slideshows);
//    $("img:eq(0)", $slideshow).addClass("active");
//    $("img:not(:visible)", $slideshow).each(function(index){
//      last = index + 1;
//      src = $(this).attr("src");
//      $('<img />').attr("src", src);
//    });

//    delay = 0;
//    pointer = 0
//    for(var i in $images){
//      console.log("should start: "+i);
//        delay += 1500;
//        setTimeout(function(){
//          object.next(pointer);
//          pointer += 1;
//        }, delay);
//    }
  };
  var changeSlide = function(index){
//    console.log("changing: "+index);
    if(locks[index] || locks[index] == undefined){
      console.log("locked: "+index);
      return;
    }
    locks[index] = true;
    next = $("img:visible", $slideshows[index]).index() + 1;
//    console.log("next img: "+next);
    if(next >= $images[index].length){
      next = 0;
    }
    $currentImg = $("img:visible", $slideshows[index]);
//console.log("$currentImg:");
//console.log($currentImg);
    $nextImg = $("img:eq("+next+")", $slideshows[index]);
//console.log("$nextImg:");
//console.log($nextImg);
    if(next > $currentImg.index()){
      $nextImg.fadeIn(duration, function(){
        $currentImg.hide(0, function(){
          locks[index] = false;
//          object.next(index);
        });
      });
    } else {
      $nextImg.show(0, function(){
        $currentImg.fadeOut(duration, function(){
          locks[index] = false;
//          object.next(index);
        });
      });
    }
  };
}

