var SlideshowBase = {
	Shows: new Array,
    scriptName: 'slideshow.js',
    scriptElement: null,
    Browser: new(function() {
        this.Opera = window.opera ? true: false;
        this.IE = document.all && !this.Opera ? true: false;
        this.IE6 = this.IE && typeof(window.XMLHttpRequest) == "undefined" ? true: false;
        this.IE8 = this.IE && typeof(document.querySelectorAll) != "undefined" ? true: false;
        this.IE7 = this.IE && !this.IE6 && !this.IE8 ? true: false;
        this.WebKit = /WebKit/i.test(navigator.userAgent) ? true: false,
        this.iPhone = /iPhone|iPod/i.test(navigator.userAgent) ? true: false;
        this.Chrome = /Chrome/i.test(navigator.userAgent) ? true: false;
        this.Safari = /Safari/i.test(navigator.userAgent) && !this.Chrome ? true: false;
        this.Konqueror = navigator.vendor == "KDE" ? true: false;
        this.Konqueror4 = this.Konqueror && /native code/.test(document.getElementsByClassName) ? true: false;
        this.Gecko = !this.WebKit && navigator.product == "Gecko" ? true: false;
        this.Gecko19 = this.Gecko && Array.reduce ? true: false;
    })(),

    getScriptElement: function(scriptName) {
        var regex = new RegExp(scriptName);
        var scripts = document.getElementsByTagName('script');
        for (var i = 0; i < scripts.length; i++) {
            if (scripts[i].src && regex.test(scripts[i].src))
            return scripts[i];
        }
        return '';
    },

    getScriptPath: function(scriptElement, scriptName) {
        var regex = new RegExp(scriptName + ".*");
        return scriptElement.src.replace(regex, '');
    },

    addScript: function(path) {
        if (this.Browser.IE || this.Browser.WebKit || this.Browser.Konqueror) {
            document.write('<script type="text/javascript" src="' + path + '"><\/script>');
        }
        else {
            var script = document.createElement('script');
            script.src = path;
            script.setAttribute('type', 'text/javascript');
            document.getElementsByTagName('head')[0].appendChild(script);
        }
    },

    addScripts: function(basePath, filenames) {
        for (var i = 0; i < filename.length; i++)
        this.addScript(basepath + filenames[i]);
    },

    addStylesheet: function(path) {
        if (this.Browser.Gecko19) {
            var link = document.createElement('link');
            link.setAttribute('rel', 'stylesheet');
            link.setAttribute('href', path);
            link.setAttribute('type', 'text/css');
            link.setAttribute('media', 'screen');
            document.getElementsByTagName('head')[0].appendChild(link);
        }
        else {
            document.write('<link rel="stylesheet" href="' + path + '" type="text/css" media="screen" />');
        }

    },

    addStylesheets: function(basePath, filenames) {
        for (var i = 0; i < filename.length; i++)
        this.addStylesheet(basepath + filenames[i]);
    },

    initPath: function() {
        /* get / set basic values */
        this.scriptElement = this.getScriptElement(this.scriptName);
        if (!this.scriptElement) {
            this.scriptName = 'slideshow.js';
            this.scriptElement = this.getScriptElement(this.scriptName);
        }

        this.BaseDir = this.getScriptPath(this.scriptElement, this.scriptName);
        if (!this.AddOnBaseDir) this.AddOnBaseDir = this.BaseDir;
        if (!this.CSSBaseDir) this.CSSBaseDir = this.BaseDir;
    },

    init: function() {
        /* add default stylesheets */
        this.addStylesheet(this.CSSBaseDir + 'slideshow.css');
        //this.addStylesheet(this.CSSBaseDir + 'myslideshow.css');

        /* ========== slideshow auto initialization on document load ==========
       * thanks to Dean Edwards
       * http://dean.edwards.name/weblog/2005/02/order-of-events/
       */
        var SLSB = this;

        /* for Mozilla, Opera 9, Safari */
        if (document.addEventListener) {
            /* for Safari */
            if (this.Browser.WebKit) {
                var _timer = setInterval(function() {
                    if (/loaded|complete/.test(document.readyState)) {
                        clearInterval(_timer);
                        SLSB.onloadInit();
                        // call the onload handler
                    }
                },
                10);
            }
            else {
                document.addEventListener("DOMContentLoaded", SLSB.onloadInit, false);
            }
        }
        else if (this.Browser.IE) {
            document.write("<script id=__ie_cf_onload defer src=javascript:void(0)><\/script>");
            var script = document.getElementById("__ie_cf_onload");
            script.onreadystatechange = function() {
                if (this.readyState == "complete") {
                    SLSB.onloadInit();
                    // call the onload handler
                }
            };
        }
				
        /* for all other browsers */
		if(window.addEvent){
			window.addEvent('load', SLSB.onloadInit, false);
		}

        /* ================================================================== */

    },

    onloadInit: function() {
        // quit if this function has already been called
        if (arguments.callee.done) return;

        // flag this function so we don't do the same thing twice
        arguments.callee.done = true;

        /* fix for mootools */
        if (window.Element && Element.implement && document.all && !window.opera) {
            for (var prop in window.SLElement.prototype) {
                if (!window.Element.prototype[prop]) {
                    var implement = {};
                    implement[prop] = window.SLElement.prototype[prop];
                    Element.implement(implement);
                }
            }
        }

        /* init all manualy created slides */
        for (var i = 0; i < SlideshowBase.Shows.length; i++) {
            SlideshowBase.Shows[i].init();
        }

        /* init the rest */
        var divs = document.getElementsByTagName('div');
        DIVS: for (var i = 0; i < divs.length; i++) {
            if (divs[i].className.match(/\bSlideshow\b/)) {
                for (var j = 0; j < SlideshowBase.Shows.length; j++) {
                    if (divs[i] == SlideshowBase.Shows[j].Container) continue DIVS;
                }
                var SLS = new Slideshow(divs[i], {},false);
                SLS.init();
            }
        }
    }
}

var Slideshow = function(container, config){
	if (container) {
      SlideshowBase.Shows.push(this);
      this.Container = container;
      this._userConf = config ? config : {};
      this.conf = {};
      this._loadedAddOns = new Array();
  } else {
      throw ('Slideshow ERROR: No container node or id given');
  }
}

Slideshow.prototype = {
	init: function () {
      if(this.isInit) return;
      this._init();
  },

	_init: function () {
      if (typeof(this.Container) == 'string') { // no node
          var container = document.getElementById(this.Container);
          if (container) {
              this.Container = container;
          } else {
              throw ('Slideshow ERROR: No element with id \''+this.Container+'\' found!');
              return;
          }
      }
      
      /* ----------  define default values */
      this.changeInt = 4000; // trigger change procedure X seconds after last change has been finished
      this.slideChangeDelay = 1000; // delay slide change procedure after cover has reached full extension
      this.coverCloseDelay = 500; // delay closing the cover after slide change procedure has been finished
      this.imgFadeDuration;
      this.coverInDuration = 2000;
      this.coverOutDuration = 1000;
      
      /* ----------  reserve CSS namespace */
	  //this.Container.addClassName('Slideshow');
	  $SL(this.Container).addClassName('Slideshow');

      /* ---------- detect GUI elements */
      var show = this.Container.getChildrenByClassName('show')[0];
      if (!show) {
          throw ('Slideshow ERROR: No element with class\'show\' found!');
          return;
      }
			this.loadIndicator = this.Container.getChildrenByClassName('loadIndicator')[0];
			this.cover = new Cover(this, this.Container.getChildrenByClassName('cover')[0]);
			this.thinkbig = new ThinkBig(this, this.Container.getChildrenByClassName('thinkbig')[0]);

      /* ---------- init item lists ---------- */
      var items = show.getChildrenByClassName('item');
			
      this.items = new Array();
      for (var i=0; i<items.length; i++) {
          var item = this.items[i] = new SlideshowItem(this, items[i], i);
          if (i > 0) { 
              item.pre = this.items[i-1];
              item.pre.next = item;
          }
      }
	  this.items[0].pre = item;
      item.next = this.items[0];
      this.isInit = true;
	  this._start();
  },

	coverFinished: function(factor){
		var SLS = this;
		if(factor == 1){
			this.startThinkBig();
			//setTimeout(function(){SLS._showNextItem()}, SLS.slideChangeDelay);
			//this._showNextItem();
		}else{
			setTimeout(function(){SLS._prepareBlend()}, SLS.changeInt);
		}
	},
	
	startThinkBig: function(){
		this.thinkbig.play();
	},
	
	onThinkBigFinished: function(){
		this._showNextItem();
	},
	
	blendFinished: function(factor){
		if(factor == 1){
			var SLS = this;
			setTimeout(function(){SLS.cover.fadeOut()}, SLS.slideChangeDelay);
		}else{
			// noop
		}
	},

	_start: function(){
		var SLS = this;
		this.showIndex = 0;
		var showItem = this.items[this.showIndex];
		showItem.display();
		this.loadIndicator.style.visibility = "hidden";
		setTimeout(function(){SLS._prepareBlend()}, SLS.changeInt);
	},
	
	_prepareBlend: function(){
		this.cover.fadeIn();
	},
	
	_showNextItem: function(){
		var nextItem = this.items[this.showIndex].next;
		this.showIndex = nextItem.index;
		nextItem.fadeIn();
	}
	
}

var SlideshowItem = function(slideshowObject, element, index){
	this.slideshowObj = slideshowObject;
	this.index = index;
	this.pre = null;
	this.next = null;
	
	/* generate deault HTML structure if item is an image */
  	if ($SL(element).nodeName == "IMG") {
      var el = document.createElement('div');
      el.className = "item";

      var cont = element.parentNode.replaceChild( el, element);
      cont.className = "content";
      el.appendChild(cont);

      if (element.title) {
          var cap = document.createElement('div');
          cap.className = "caption";
          cap.innerHTML = element.title;
          el.appendChild(cap);
      }
      element = el;
  	}
	this.element = element;
}

SlideshowItem.prototype = {
	display: function(){
		this.element.style.visibility = "visible";
	},
	
	hide: function(){
		this.element.style.visibility = "hidden";
	},
	
	fadeIn: function(){
		var SLSI = this;
		//setTimeout(function () { SLSI._fade(1, 0); }, 1);		
		this.pre.fadeOut();
		jQuery(this.element).css({visibility: 'visible', opacity: "0"});
		jQuery(this.element).animate({opacity: "1"}, 1500, "linear", function(){SLSI.slideshowObj.blendFinished(1)});
	},
	
	fadeOut: function(){
		var SLSI = this;
		//setTimeout(function () { SLSI._fade(-1, 100); }, 1);
		jQuery(this.element).animate({opacity: "0"}, 1500, "linear", function(){SLSI.slideshowObj.blendFinished(-1)});
	},
	
	_fade: function(factor, step){
		this._setOpacity((step / 100));
		step += (2 * factor);
		if(step > 100){
			this._setOpacity(1);
			this.slideshowObj.blendFinished(factor);
		}else if(step < 0){
			this._setOpacity(0);
			this.slideshowObj.blendFinished(factor);
		}else{
			var SLSI = this;
			setTimeout(function () { SLSI._fade(factor, step); }, 1);
		}
	},
	
	_setOpacity: function(opacity){
		this.element.style.opacity = opacity;
		this.element.style.filter = "alpha(opacity=" + (opacity * 100) + ")"; // IE
		this.element.style.visibility = "visible";
	}
}

var Cover = function(slideshowObject, element){
	this.slideshowObj = slideshowObject;
	this.coverElement = element;
	this.inDuration = this.slideshowObj.coverInDuration;
	this.outDuration = this.slideshowObj.coverOutDuration;
	this.coverElement.style.width = (0 + "%");
}

Cover.prototype = {
	fadeIn: function(){
		jQuery(this.coverElement).css({visibility: "visible"})
		var C = this;
		var i = C.inDuration / 100;
		//setTimeout(function () { C._fade(1, 0, i); }, i);
		jQuery(this.coverElement).animate({width: "100%"}, C.inDuration, "swing", function(){C.slideshowObj.coverFinished(1)});
	},
	
	fadeOut: function(){		
		var C = this;
		var i = C.outDuration / 100;
		//setTimeout(function () { C._fade(-1, 100, i); }, i);
		jQuery(this.coverElement).animate({width: "0%"}, C.outDuration, "swing", function(){C.slideshowObj.coverFinished(-1)});
	},
	
	_fade: function(factor, step, i){
		var currentWidth = this._getWidth();
		
		if(factor == 1){
			var change = Math.ceil((100 - currentWidth) / 15);
		}else{
			var change = Math.ceil((currentWidth) / 15);
		}
		step += (1 * factor);

		if(change <= 0){
			var finalWidth = factor == 1 ? 100 : 0;
			this._setWidth(finalWidth);
			this.slideshowObj.coverFinished(factor);	
		}else{
			var setWidth = factor == 1 ? currentWidth + change : currentWidth - change
			this._setWidth(setWidth);
			var C = this;
			setTimeout(function () { C._fade(factor, step, i); }, i);
		}
		/*
		this._setWidth(step);
		step += (1 * factor);
		if(step > 100){
			this._setWidth(100);
			this.slideshowObj.coverFinished(factor);
		}else if(step < 0){
			this._setWidth(0);
			this.slideshowObj.coverFinished(factor);
		}else{
			var C = this;
			setTimeout(function () { C._fade(factor, step, int); }, int);
		}
		*/
	},
	
	_setOpacity: function(opacity){
		this.coverElement.style.opacity = opacity;
		this.coverElement.style.filter = "alpha(opacity=" + (opacity * 100) + ")"; // IE
	},
	
	_setWidth: function(width){
		this.coverElement.style.width = (width + "%");
	},
	
	_getWidth: function(){
		var w = this.coverElement.style.width;
		w = w == "" ? 0 : parseInt(w);
		return w;
	}
}

var ThinkBig = function(slideshowObject, element){
	this.slideshowObj = slideshowObject;
	this.$element = jQuery(element);
	this.$claim = this.$element.find(".claim");
	this.$claimImg = this.$element.find(".claimImg");
	//this.$logo = this.$element.find(".claimLogo");
	this.$logoImg = this.$element.find(".logoImg");
	this.$blanks = this.$element.find(".blank");
	this.showLogo = false;
	var $container = this.$element.closest(".SlideshowContainer");
	
	
	this.w = $container.width();
	this.h = $container.height();
	this.claimMaxW = 200
	this.maxX = this.w - this.claimMaxW;
	this.minX = (this.w / 2);
	this.randRange = this.maxX - this.minX - this.claimMaxW;
	this.blankMinDim = 30;
	this.blankMaxDim = 60;
	this.blankDimDiff = this.blankMaxDim - this.blankMinDim;
	this.blankMinTargetDim = 100;
	this.blankMaxTargetDim = this.h - 20;
	this.blankTargetDimDiff = this.blankMaxTargetDim - this.blankMinTargetDim;
}
ThinkBig.prototype = {
	play: function(){
		var TB = this;
		TB.$element.css({visibility: "visible"});
		TB.$claim.css({visibility: "visible", left: "0px", width: "100px", height: "100px", opacity: "0"});
		if(this.showLogo){
			TB.$logoImg.css({visibility: "visible", display: "block", width: "100%", height: "100%"});
			TB.$claimImg.css({visibility: "hidden", display: "none"});
		}else{
			TB.$claimImg.css({visibility: "visible", display: "block", width: "100%", height: "100%"});
			TB.$logoImg.css({visibility: "hidden", display: "none"});
		}
		this.showLogo = !this.showLogo;
		TB.$blanks.each(function(i, e){
			var $e = jQuery(e);
			var currentPos = $e.position();
			var currentX = currentPos.left;
			var startDim = (TB.blankMinDim + (Math.floor(Math.random() * TB.blankDimDiff)));
			var endDim = (TB.blankMinDim + (Math.floor(Math.random() * TB.blankDimDiff)));
			var targetDim = (TB.blankMinTargetDim + (Math.floor(Math.random() * TB.blankTargetDimDiff)));
		
			var yPos = (5 + (Math.floor(Math.random() * (TB.h - targetDim - 10))));
			
			var randRange = (TB.w / 2) - (targetDim * 2); 
			var tX_1 = (TB.minX + Math.floor(Math.random() * randRange));
			var tX_2 = currentX > 0 ? 0 : (TB.w - endDim);
			
			var duration = 1600 + Math.floor(Math.random() * 1000);
			var d_1 = duration / 2;
			var d_2 = duration / 2;
			
			startDim += "px";
			targetDim += "px";
			endDim += "px";

			yPos += "px";
			tX_1 += "px";
			tX_2 += "px";
			
			$e.css({visibility: "visible", top: yPos, width: startDim, height: startDim});
			$e.animate({left: tX_1, width: targetDim, height: targetDim, opacity: "0.5"}, d_1).animate({left: tX_2, width: endDim, height: endDim, opacity: "0"}, d_2);
		});
		tX_1 = TB.minX + (Math.floor(Math.random() * this.randRange)) + "px";
		tX_2 = TB.maxX + "px";
		TB.$claim.animate({left: tX_1, width: "150px", height: "150px", opacity: "0.7"}, 1500, "easeOutQuart").animate({left: tX_2, opacity: "0"}, 1000, "easeInQuart", function(){TB._finished();});						 
		//TB.$claimImg.animate({width: "150px", height: "150px"}, 1500, "easeOutQuart");
	},
	
	_finished: function(){
		this.$blanks.each(function(i, e){
			var dim = "0px";
			jQuery(e).css({visibility: "hidden", left:"0px", width: dim, height: dim, opacity: "0"});
		});
		this.slideshowObj.onThinkBigFinished();
	}
}

/* ==================== extendig javascript/DOM objects ==================== */

/*
 *  adds bind method to Function class
 *  http://www.digital-web.com/articles/scope_in_javascript/
 */

if (!Function.bind) {
    Function.prototype.bind = function(obj) {
        var method = this;
        return function () {
            return method.apply(obj, arguments);
        };
    };
}


/*
 * extending Math object
 */
if (!Math.erf2) {
    // error function (http://en.wikipedia.org/wiki/Error_function), implemented as erf(x)^2
    Math.erf2 = function (x) {
        var a = - (8*(Math.PI -3)/(3*Math.PI*(Math.PI -4)));
        var x2 = x*x;
        var f = 1 - Math.pow(Math.E, -x2 * (4/Math.PI + a*x2)/(1+a*x2));
        return f;
    };
}

if (!Math._2PI05) {
    Math._2PI05 = Math.sqrt(2*Math.PI);
}

if (!Math.normDist) {
    // normal distribution
    Math.normDist = function (x, sig, mu) {
        if (!sig) var sig = 1;
        if (!mu) var mu = 0;
        if (!x) var x = - mu;
        return 1/(sig * Math._2PI05) * Math.pow(Math.E, - (x-mu)*(x-mu)/(2*sig*sig) );
    };
}

if (!Math.normedNormDist) {
    Math.normedNormDist = function (x, sig, mu) {
        return this.normDist(x, sig, mu)/this.normDist(mu, sig, mu);
    };
}

if (!Math.exp) {
    Math.exp = function(x) {
        return Math.pow(Math.E, x);
    };
}

if (!Math.ln) {
    Math.ln = Math.log;
}

if (!Math.log2) {
    Math.log2 = function (x) {
        return Math.log(x)/Math.LN2;
    };
}

if (!Math.log10) {
    Math.log10 = function (x) {
        return Math.log(x)/Math.LN10;
    };
}

if (!Math.logerithm) {
    Math.logerithm = function (x, b) {
        if (!b || b == Math.E)
            return Math.log(x);
        else if (b == 2)
            return Math.log2(x);
        else if (b == 10)
            return Math.log10(x);
        else
            return Math.log(x)/Math.log(b);
    };
}


/*
 * extending Event object
 */
if (!Event) var Event = {};

if (!Event.stop) {
    Event.stop = function (event) {
        event.cancelBubble = true;
        if (event.preventDefault) event.preventDefault();
        if (event.stopPropagation) event.stopPropagation();
        return false;
    };
}

/*
 * extending Element object
 */
if (document.all && !window.opera) {
    window.$SL = function (el) {
        if (typeof el == "string") {
            return window.$SL(document.getElementById(el));
        }
        else {
            if (SLElement.prototype.extend && el && !el.extend) SLElement.prototype.extend(el);
        }
        return el;
    };
} else {
    window.$SL = function (el) {
        return el;
    };
}

if (!window.HTMLElement) {
    SLElement = {};
    SLElement.prototype = {};
    SLElement.prototype.extend = function (el) {
        for (var method in this) {
            if (!el[method]) el[method] = this[method];
        }
    };
}
else {
    SLElement = window.HTMLElement;
}


/*
 * Thanks to Peter-Paul Koch
 * http://www.quirksmode.org/js/findpos.html
 */
if (!SLElement.findPos) {
    SLElement.prototype.findPos = function() {
        var obj = this;
        var curleft = curtop = 0;
        try {
            if (obj.offsetParent) {
                curleft = obj.offsetLeft;
                curtop = obj.offsetTop;
                while (obj = obj.offsetParent) {
                    curleft += obj.offsetLeft;
                    curtop += obj.offsetTop;
                }
            }
        }
        catch (ex) {}
        return {left:curleft, top:curtop};
    };
}

if (!SLElement.getDimensions) {
    SLElement.prototype.getDimensions = function() {
        return {width: this.clientWidth, height: this.clientHeight};
    };
}

/*
 * checks if an element has the class className
 */
if (!SLElement.hasClassName) {
    SLElement.prototype.hasClassName = function(className) {
        return (new RegExp('\\b'+className+'\\b').test(this.className));
    };
}

/*
 * adds the class className to the element
 */ 
if (!SLElement.addClassName) {
    SLElement.prototype.addClassName = function(className) {
        if(!this.hasClassName(className)) {
           this.className += (this.className ? ' ':'') + className ;
        }
    };
}

/*
 * removes the class className from the element el
 */ 
if (!SLElement.removeClassName) {
    SLElement.prototype.removeClassName = function(className) {
        this.className = this.className.replace(new RegExp('\\b'+className+'\\b'), '').replace(/\s\s/g,' ');
    };
}

/*
 * removes or adds the class className from/to the element el
 * depending if the element has the class className or not.
 */
if (!SLElement.toggleClassName) {
    SLElement.prototype.toggleClassName = function(className) {
        if(this.hasClassName(className)) {
            this.removeClassName(className);
        } else {
            this.addClassName(className);
        }
    };
}

/*
 * returns all children of element el, which have the class className
 */
if (!SLElement.getChildrenByClassName) {
    SLElement.prototype.getChildrenByClassName = function(className) {
        var children = new Array();
        for (var i=0; i < this.childNodes.length; i++) {
            var c = this.childNodes[i];
            if (c.nodeType == 1 && $SL(c).hasClassName(className)) {
                children.push(c);
            }
        }
        return children;
    };
}

/*
 * Browser independent event handling method.
 * adds the eventListener  eventName to element el and attaches the function method to it.
 */
if (!SLElement.addEvent) {
    SLElement.prototype.addEvent = function(eventName, method, capture) {
        if (this.addEventListener)
            this.addEventListener(eventName, method, capture);
        else
            this.attachEvent('on'+eventName, method);
    };
}
   
/*
 * Browser independent event handling method.
 * removes the eventListener  eventName with the attached function method from element el.
 */
if (!SLElement.removeEvent) {
    SLElement.prototype.removeEvent = function(eventName, method, capture) {
        if (this.removeEventListener)
            this.removeEventListener(eventName, method, capture);
        else
            this.detachEvent('on'+eventName, method);
    };
}

/*
 * Browser independent event handling method.
 * adds the eventListener  eventName to element el and attaches the function method to it.
 */
if (!window.addEvent) {
    window.addEvent = function(eventName, method, capture) {
        if (this.addEventListener) {
            this.addEventListener(eventName, method, capture);
        } else {
            if (eventName != 'load' && eventName != 'resize')
                document.attachEvent('on'+eventName, method);
            else
                this.attachEvent('on'+eventName, method);
        }
    };
}
   
/*
 * Browser independent event handling method.
 * removes the eventListener  eventName with the attached function method from element el.
 */
if (!window.removeEvent) {
    window.removeEvent = function(eventName, method, capture) {
        if (this.removeEventListener) {
            this.removeEventListener(eventName, method, capture);
        } else {
            if (eventName != 'load' && eventName != 'resize')
                document.detachEvent('on'+eventName, method);
            else
                this.detachEvent('on'+eventName, method);
        }
    };
}

/* ==================== start it all up ==================== */

SlideshowBase.initPath();
SlideshowBase.init();
