
/**
 *
 *  Rotator                             ( 2010-10-01 ) 
 *
 *  Vstupni objekt:
 *
 *  config.cover                        [HTMLElement] obalovy html element 
 *  config.tagName                      [String] jmenu tagu pro vyber elementu 
 *  config.className                    [String] jmeno html tridy k aplikovani na objekty ( divy )
 *  config.simpleLogger                 [SimpleLogger] SimpleLogger objekt 
 *  config.infinite                     [bool] nekonecne smycka ( pro Prev & Next )
 *  config.fadeEffect                   [bool] fade efekt
 *  config.fadeSpeed                    [int] rychlost prechodu, 10 .. 10000
 *  config.random                       [bool] pouzivat random pri funkci pri prechodu mezi prvky 
 *  
 *  Metody:
 *  
 *  random                              zobrazi random prvek
 *  my                                  zobrazi prvek s indexem i
 *      param i                         index do pole InDivs ( pole rotovanych elementu ) 
 *  next                                zobrazi dalsi prvek
 *  prev                                zobrazi predchzi prvek 
 *  startAuto                           automaticka zmena v danem intervalu
 *      param delay                     casova prodleva v milisec.
 *  stopAuto                            zastaveni automaticke zmeny
 *  toggleAuto                          prepinani mezi start a stop auto.
 *      param delay                     casova prodleva v milisec.
 *  
 *  Settery / Gettery:
 *  
 *  isFadeFinished                      [bool] vraci, zda jiz byl fade efekt dokoncen.
 *  setFadeEffect                       nastavi fadeEffect
 *      param val                       [bool] nova hodnota
 *  setFadeSpeed                        nastavi rychlost fadeEffect
 *      param val                       [int] pocet milisekund
 *      
 *  Eventy:                             (pro prepsani, u instance nahradit vlastni funkci)
 *  
 *  onHideStart                         metoda volana pred schovanim elementu
 *      InDivs                          pole rotovanych elementu
 *      Index                           index do prechoziho pole, ukazuje na schovavany element   
 *  onShowStart                         metoda volana pred zobrazenim elementu
 *      InDivs                          pole rotovanych elementu
 *      Index                           index do prechoziho pole, ukazuje na zobrazovany element
 *  onHideFinished                      metoda volana po schovani elementu
 *      InDivs                          pole rotovanych elementu
 *      Index                           index do prechoziho pole, ukazuje na schovavany element   
 *  onShowFinished                      metoda volana po zobrazeni elementu
 *      InDivs                          pole rotovanych elementu
 *      Index                           index do prechoziho pole, ukazuje na zobrazovany element
 *
 */
 
function Rotator(config) {
    if(config == null) {
        throw new Error("Rotator: Neni zadan config objekt!");
        return;
    }
    if(config.cover == null) {
        throw new Error("Rotator: Neni zadan obalovy element!");
    }
    
    var This = this;
    var Config = config;
    var InDivs = new Array();
    var Index = 0;
    var Logger = (config.simpleLogger) ? config.simpleLogger : (window.console) ? console : null;
    var Cover = config.cover;
    var TagName = (config.tagName) ? config.tagName : "div";
    var ClassName = (config.className != null) ? config.className : "rotator-item";
    var Infinite = (config.infinite) ? config.infinite : false;
    var FadeEffect = (config.fadeEffect != null && config.fadeEffect == true) ? true : false;
    var FadeSpeed = (config.fadeSpeed != null && config.fadeSpeed >= 10 && config.fadeSpeed <= 10000) ? config.fadeSpeed : 500;
    var FadeFinished = true; 
    var Random = config.random;
    var Timer = null;
    var CallPrevAfterFade = false;
    var CallNextAfterFade = false;
    var CallMyAfterFade = -1;
    
    function init() {
        var inDivs = Cover.getElementsByTagName(TagName);
        for(var i = 0; i < inDivs.length; i ++) {
            if((ClassName != "") ? (inDivs[i].className.indexOf(ClassName) != -1) : true) {
                InDivs[InDivs.length] = inDivs[i];
                inDivs[i].style.display = "none";
            }
        }
        Logger.info("Length: " + InDivs.length, 2);
        if(Random == false) {
            FadeEffect = false;
            showEl(0);
            FadeEffect = Config.fadeEffect;
        } else {
            This.random();
        }
    };
    
    this.next = function() {
        Logger.log("FadeFinished: " + FadeFinished, 2);
        if(FadeFinished) {
            if(CallPrevAfterFade) {
                Logger.log("Post PREV call", 2);
                CallPrevAfterFade = false;
                This.prev();
                return;
            } else if(CallNextAfterFade) {
                Logger.log("Post NEXT call", 2);
                CallNextAfterFade = false;
                This.next();
                return;
            } else if(CallMyAfterFade != -1) {
                Logger.log("Post MY call", 2);
                This.my(CallMyAfterFade);
                CallMyAfterFade = -1;
                return;
            } else if((Infinite && InDivs.length == (Index + 1)) || InDivs.length > (Index + 1)) {
                hideEl(Index);
                if(InDivs.length > (Index + 1)) {
                    Index ++;
                } else {
                    Index = 0;
                }
                showEl(Index);
            }
        } else {
            CallNextAfterFade = true;
            Logger.log("CallNextAfterFade setuped up", 2);
        }   
    };
                
    this.prev = function() {
        if(FadeFinished) {
            if((Infinite && Index == 0) || Index > 0) {
                hideEl(Index);
                if(Index > 0) {
                    Index --;
                } else {
                    Index = InDivs.length - 1;
                }
                showEl(Index);
            }
        } else {
            CallPrevAfterFade = true;
        }
    };
    
    this.random = function() {
        Logger.log("FadeFinished: " + FadeFinished, 2);
        if(FadeFinished) {
            hideEl(Index);
            do {
                i = Math.round(Math.random() * (InDivs.length - 1));
            } while(i == Index);
            Index = i;
            showEl(Index);
        }
    };
    
    this.my = function(index) {
        if(index > -1 && index < InDivs.length) {
            Logger.log("FadeFinished: " + FadeFinished, 2);
            if(FadeFinished) {
                hideEl(Index);
                Index = index;
                showEl(Index);
            } else {
                CallMyAfterFade = index;
            }
        }
    };
    
    this.toggleAuto = function(delay) {
        if(Timer == null) {
            This.startAuto(delay);
        } else {
            This.stopAuto();
        }
    };
    
    this.startAuto = function(delay) {
        if(Random == false) {
            Timer = window.setInterval(This.next, delay);
        } else {
            Timer = window.setInterval(This.random, delay);
        }
    };
    
    this.stopAuto = function() {
        window.clearInterval(Timer);
        Timer = null;
    };
    
    
    this.onHideFinished = function(InDivs, Index) {
       
    };
    
    
    this.onHideStart = function(InDivs, Index) {
       
    };
    
    
    this.onShowFinished = function(InDivs, Index) {
       
    };
    
    
    this.onShowStart = function(InDivs, Index) {
       
    };
                
    function hideEl(index) {
        This.onHideStart(InDivs, Index);
        Logger.info("Hide Index: " + Index, 1);
        if(FadeEffect) {
            FadeFinished = false;
            jQuery(InDivs[index]).fadeOut(FadeSpeed, function() {
                FadeFinished = true;
                This.onHideFinished(InDivs, Index);
            });
        } else {    
            InDivs[index].style.display = 'none';
        }
    };
    
    function showEl(index) {
        This.onShowStart(InDivs, Index);
        Logger.info("Show Index: " + Index, 1);
        if(FadeEffect) {
            FadeFinished = false;
            jQuery(InDivs[index]).fadeIn(FadeSpeed, function() {
                FadeFinished = true;
                This.onShowFinished(InDivs, Index);
            });
        } else {
            InDivs[index].style.display = '';
        }
    };
    
    this.isFadeFinished = function() {
        return FadeFinished;
    };
    
    this.setFadeEffect = function(val) {
        if(val != null) {
            if(val == true) {
                FadeEffect = true;
            } else if(val == false) {
                FadeEffect = false;
            } else {
                throw new Error("[ROTATOR]: Incorrect value passed to 'setFadeEffect'!");
            }
        } else {
            throw new Error("[ROTATOR]: Incorrect value passed to 'setFadeEffect'!");
        }
    };
    
    this.setFadeSpeed = function(val) {
        if(val != null) {
            if(val >= 10 && val <= 10000) {
                FadeSpeed = val;
            } else {
                throw new Error("[ROTATOR]: Incorrect value passed to 'setFadeSpeed'!");
            }
        } else {
            throw new Error("[ROTATOR]: Incorrect value passed to 'setFadeSpeed'!");
        }
    };
    
    this.addEvent = function(obj, ev, func, b) {
        if(obj.addEventListener) {
            obj.addEventListener(ev, func, b);
        } else {
            obj.attachEvent("on" + ev, func);
        }
    };
    
    this.removeEvent = function(obj, ev, func, b) {
        if(obj.addEventListener) {
            obj.removeEventListener(ev, func, b);
        } else {
            obj.detachEvent("on" + ev, func);
        }
    };
    
    this.stopEvent = function (event) {
        if(navigator.appName != "Microsoft Internet Explorer") {
            event.stopPropagation();
            event.preventDefault();
        } else {
            event.cancelBubble = true;
            event.returnValue = false;
        }
    };
    
    init();
};
