/*
 * Initiert und steuert die Scrollboxen für Webservice-Inhalte
 * 
 * @author Wolfgang Merkens <wm@traveltainment.de>
 * @copyright  2010 Traveltainment AG
 */
 
/*
 * Erweitere alle Funktionsobjekte um eine Methode »bind« über die 
 * prototype-Eigenschaft des Function-Konstruktors.
 */
if (typeof(Function.prototype.bind) != 'function') {
    Function.prototype.bind = function(object) {
        // Speichere die gegenwärtige Funktion in »theMethod«.
        var theMethod = this;
        // Die Closure-Funktion schließt »theMethod«, »object« und »arguments« ein.
        // Rufe die Funktion im Kontext des Objektes »object« auf,
        // reiche dabei die restlichen Parameter durch und
        // gib den Rückgabewert der Funktion zurück.
        return function() {
            return theMethod.apply(object, arguments);
        }
    }
}

/*
 * Konstruktor
 */
function TTScrollBox() {
    this.BoxObj         = {};
    this.Boxes          = {};
    this.BoxesStat      = {};
    this.boxHeight      = '600'; //Default Höhe der Boxen (600px)
    this.loadImage      = ''; //Name der Grafik für den Ladevorgang
    this.openEffect     = true; //Scrolleffekt beim Öffnen ja/nein
    this.closeEffect    = true; //Scrolleffekt beim Schließen ja/nein
    this.durationOpen   = 500; //Default-Scroll-Dauer in ms (500)
    this.durationClose  = 300; //Default-Scroll-Dauer in ms (300)
    this.reqDuration    = null; //akt. benutzte Scrolldauer (wird an js-func navigate übergeben)
    this.stepTime       = 20; //Default-Scroll-Speed in ms (20) 

}

/*
 * Box für scrollbaren Webservice-Content generieren
 */
TTScrollBox.prototype.boxControl = function(elem) {
    if (typeof(elem) != 'object') {
        var elem = document.getElementById(elem);
    }
    
    var obj = {};
    
    //Default-Startwerte
    obj.BoxId        = '';
    obj.boxStatus    = '';
    obj.ScrollType   = '';
    obj.boxAction    = '';
    obj.procedure    = '';
    obj.RefBox       = null;
    obj.ReqArt       = '';
    obj.Params       = '';
    obj.SourceElem   = elem;
    obj.socketOpen   = new Object();
    obj.socketClose  = new Object();
    obj.Port         = '';
    obj.bottomRefElem = null;
    obj.boxBottom     = null;
    obj.boxCloseElem  = null;
    // --- Attribute der geklickten Box definieren
    if (typeof(elem) == 'object' && typeof(elem.attributes) == 'object' && elem.attributes.length > 0) {
        obj.Elem       = elem;
        obj.RefBox     = document.getElementById(elem.getAttribute('scrollreference', 0));
        obj.ScrollType = elem.getAttribute('scrolltype', 0);
        obj.ReqArt     = elem.getAttribute('scrollrequest', 0);
        obj.forceRequest  = Boolean(elem.getAttribute('scrollforcerequest', 0));
        obj.Params     = elem.getAttribute('scrollparams', 0);
        obj.Port       = elem.getAttribute('scrollport', 0);
        if (obj.Port == null) {
            obj.Port = '';
        }
        obj.withClose = false;
        if (typeof elem.getAttribute('scrollWithClose', 0) && elem.getAttribute('scrollWithClose', 0) == '1') {
            obj.withClose = true;    
        }
        // --- params-string zerlegen ---
        if (obj.Params != null && obj.Params != '') {
            var tmpParam = obj.Params.split('&');
            if (tmpParam.length > 0) {
                for(var i = 0; i < tmpParam.length; i ++) {
                    var tmpRequest = tmpParam[i].split('=');
                    if (tmpRequest[0] == 'idContent') {
                        obj.BoxId = tmpRequest[1];
                        break;
                    }
                }
            }
        }
        
        if (obj.BoxId == null || obj.BoxId == '' || obj.ScrollType == null || obj.ScrollType == '') {
            return false;
            //alert('No Id!')
        }
        
        obj.ObjId = obj.BoxId + '_' + obj.ScrollType;
        
        if (obj.withClose == true) {
            this.BoxesStat[obj.BoxId] = null;
            this.Boxes[obj.ObjId]     = null;
        }
        
        // --- Boxen und deren Status speichern ----------------------------------
        if (typeof this.BoxesStat[obj.BoxId] == 'undefined' || this.BoxesStat[obj.BoxId] == null) {
            this.BoxesStat[obj.BoxId]       = {};
            this.BoxesStat[obj.BoxId].stat  = 0;
            this.BoxesStat[obj.BoxId].id    = '';
            this.BoxesStat[obj.BoxId].newId = '';
            this.BoxStat                    = this.BoxesStat[obj.BoxId];
        } else {
            this.BoxStat = this.BoxesStat[obj.BoxId];
        }
        
        if (typeof this.Boxes[obj.ObjId] == 'undefined' || this.Boxes[obj.ObjId] == null) {
            this.Boxes[obj.ObjId] = obj;
            this.BoxObj           = obj;    
        } else {
            this.BoxObj = this.Boxes[obj.ObjId];
        }
        
        // --- Box definieren ---
        this.defineTheBox();
        // --- Weitere Prozedur bestimmen ---
        this.setBoxProcedure();
    } else {
        //alert('No iHIB Action Element!');
    }
}

/*
 * Entscheidet, welche 'open/close'-Prozedur gestartet wird
 */
TTScrollBox.prototype.setBoxProcedure = function() {
    
    
    /*
    console.debug('---------------------------------------------');
    console.debug(this.BoxStat.stat);
    console.debug(this.BoxStat.id);
    console.debug(this.BoxStat.newId);
    */

    
    if (this.BoxObj.boxStatus == '') {
        // --- erst andere BOX schliessen ---
        if (this.BoxStat.stat == 1) {
            var tmpId   = this.BoxObj.ObjId;
            this.BoxObj = this.Boxes[this.BoxStat.id];
            this.BoxObj.boxStatus = 'close';
            this.closeTheBox();
            this.BoxStat.newId = tmpId;
        } else {
            this.BoxObj.boxStatus = 'open';
            this.openTheBox();
            navigate(this.BoxObj.Params, 'scrollContent_' + this.BoxObj.ScrollType + '_' + this.BoxObj.BoxId, this.loadImage, this.BoxObj.ReqArt, this.BoxObj.Port, this.reqDuration);
            this.BoxStat.stat = 1;
            this.BoxStat.id   = this.BoxObj.ObjId;  
        } 
    } else if (this.BoxObj.boxStatus == 'close') {
        // --- erst andere BOX schliessen ---
        if (this.BoxStat.stat == 1) {
            var tmpId             = this.BoxObj.ObjId;
            this.BoxObj           = this.Boxes[this.BoxStat.id];
            this.BoxObj.boxStatus = 'close';
            this.closeTheBox();
            this.BoxStat.newId = tmpId;
        } else {
            this.BoxObj.boxStatus = 'open';
            this.openTheBox();
            refreshContent(this.BoxObj.BoxId, this.BoxObj.ScrollType);
            this.BoxStat.stat = 1;
            this.BoxStat.id   = this.BoxObj.ObjId;            
        }
    } else if (this.BoxObj.boxStatus == 'open') {
        this.BoxObj.boxStatus = 'close';
        this.closeTheBox();
        this.BoxStat.stat = 0;
        this.BoxStat.id   = '';
    }
}

/*
 * Wurde Container für diese Box schon einmal angelegt oder muß dieser 
 * neu erzeugt werden?
 */
TTScrollBox.prototype.defineTheBox = function() {
    var isDefined = true;
    //Container neu anlegen?
    if(document.getElementById('scrollContent_' + this.BoxObj.ScrollType + '_' + this.BoxObj.BoxId) == null) {
        if (typeof(this.BoxObj.RefBox) != 'undefined') {
            //id für newDiv anlegen
            var newDiv          = document.createElement('div');
            var newDiv_id       = document.createAttribute('id');
            newDiv_id.nodeValue = 'scrollContent_' + this.BoxObj.ScrollType + '_' + this.BoxObj.BoxId;
            newDiv.setAttributeNode(newDiv_id);
            //class für newDiv anlegen
            var newDiv_class       = document.createAttribute('class');
            newDiv_class.nodeValue = 'tt_scrollContent_' + this.BoxObj.ScrollType;
            newDiv.setAttributeNode(newDiv_class);
            // --- func insertAfter fügt div hinter Referenz-Box ein
            this.insertAfter(this.BoxObj.RefBox, newDiv);
            // abfangen
            if(document.getElementById('scrollContent_' + this.BoxObj.ScrollType + '_' + this.BoxObj.BoxId) == null) {
                return false;
            }
            //Bottom-Zeile für Content-Box?
            this.BoxObj.bottomRefElem = document.getElementById('scrollContent_' + this.BoxObj.ScrollType + '_' + this.BoxObj.BoxId);
            //ind. callback-Func?
            if (typeof(ttsb_createBottomContent) == 'function') {
                this.BoxObj.boxBottom = ttsb_createBottomContent(this, this.BoxObj);
            } else {
                //standard-Func
                this.createBottomContent();
            }
        } else {
            isDefined = false;
        }
    }
    if (isDefined) {
        this.BoxObj.box = document.getElementById('scrollContent_' + this.BoxObj.ScrollType + '_' + this.BoxObj.BoxId);
        if (this.BoxObj.box != null) {
            this.BoxObj.box.style.height  = '0px';
            this.BoxObj.box.style.display = 'none';
            if (this.BoxObj.boxBottom == null) {
                this.BoxObj.boxBottom = document.getElementById('scrollContentBottom_' + this.BoxObj.ScrollType + '_' + this.BoxId);
                if (this.BoxObj.boxCloseElem == null) {
                    this.BoxObj.boxCloseElem = document.getElementById('scrollContentBottomClose_' + this.BoxObj.ScrollType + '_' + this.BoxObj.newBoxId);
                }
            }
            if (this.BoxObj.boxBottom != null) {
                this.BoxObj.boxBottom.style.display = 'none';
                if (this.BoxObj.boxCloseElem != null) {
                    this.BoxObj.boxCloseElem.style.display = 'none';
                }
            }
        }
    }
    return isDefined;
}

//Neue Contentbox wird im dom-baum hinter Referenz-Box angelegt
TTScrollBox.prototype.insertAfter = function(referenceNode, newNode) {
    if (referenceNode) {
        if (referenceNode.parentNode) {
            if (referenceNode.nextSibling) {
                referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
            } else {
                referenceNode.parentNode.appendChild(newNode);
            }
        } else {
            referenceNode.appendChild(newNode);
        }
    }
}

/*
 * Definiert eine neue Box und öffnet sie
 */
TTScrollBox.prototype.setNewBoxProcess = function() {
    if (this.defineTheBox()) {
        this.actBoxId      = this.newBoxId;
        this.actScrollType = this.newScrollType;
        this.actSourceElem = this.newSourceElem;
        this.actRefBox     = this.newRefBox;
        this.actPort       = this.newPort;
        this.boxStatus     = this.updateLivingBoxes();
        if (this.boxStatus == 'old') {
            this.openTheBox();
            refreshContent(this.newBoxId, this.newScrollType);
        } else if (this.boxStatus == 'new') {
            this.openTheBox();
            navigate(this.newParams, 'scrollContent_' + this.newScrollType + '_' + this.newBoxId, this.loadImage, this.newReqArt, this.newPort, this.reqDuration);
        }
    }
}



/*
 * Öffnet eine neue Box
 */
TTScrollBox.prototype.openTheBox = function() {
    this.boxAction = 'open';
    
    if (this.BoxObj.box) {
        if (this.boxHeight > 0) {
            if (this.openEffect) {
                this.reqDuration = this.durationOpen;
                this.BoxObj.box.style.height  = '0px';
                this.BoxObj.box.style.display = 'block';
                this.transform(0, this.boxHeight);
               
                if (this.BoxObj.boxBottom != null) {
                    this.BoxObj.boxBottom.style.display = 'block';
                    if (this.BoxObj.boxCloseElem != null) {
                        this.BoxObj.boxCloseElem.style.display = 'block';
                    }
                }
            } else {
                this.BoxObj.box.style.height  = this.boxHeight + 'px';
                this.BoxObj.box.style.display = 'block'; 
                if (this.BoxObj.boxBottom != null) {
                    this.BoxObj.boxBottom.style.display = 'block';
                    if (this.BoxObj.boxCloseElem != null) {
                        this.BoxObj.boxCloseElem.style.display = 'block';
                    }
                }
            }
            //ind. callback-Func?
            if (typeof(ttsb_setBoxStatusOpen) == 'function') {
                this.setSocketOpen();
                ttsb_setBoxStatusOpen(this.BoxObj.socketOpen);
            }
        }
    }
}

/*
 * Schließt eine Box 
 */
TTScrollBox.prototype.closeTheBox = function() {
    this.boxAction = 'close';
    
    if (this.BoxObj.box) {
        if (this.boxHeight > 0) {
            if (this.BoxObj.boxBottom != null) {
                if (this.BoxObj.boxCloseElem != null) {
                    this.BoxObj.boxCloseElem.style.display = 'none';
                }
                this.BoxObj.boxBottom.style.display = 'none';
            }
            if (this.closeEffect) {
                this.reqDuration = this.durationClose;
                this.transform(0, this.boxHeight);
            } else {
                this.BoxObj.box.style.height  = '0px';
                this.BoxObj.box.style.display = 'none';
                //ind. callback-Func?
                if (typeof(ttsb_setBoxStatusClose) == 'function') {
                    this.setSocketClose();
                    ttsb_setBoxStatusClose(this.BoxObj.socketClose);
                }
            }
        }
    }
}

/*
 * Standard-Bottom-Zeile unterhalb der ScrollContentBox
 */
TTScrollBox.prototype.createBottomContent = function() {
    // --- Äußeres Div der bottom-Zeile erzeugen
    var mainDiv = document.createElement('div');
    //id für mainDiv anlegen
    var mainDiv_id       = document.createAttribute('id');
    mainDiv_id.nodeValue = 'scrollContentBottom_' + this.BoxObj.ScrollType + '_' + this.BoxObj.BoxId;
    mainDiv.setAttributeNode(mainDiv_id);
    //class für mainDiv anlegen
    var mainDiv_class       = document.createAttribute('class');
    mainDiv_class.nodeValue = 'tt_scrollBoxBottom';
    mainDiv.setAttributeNode(mainDiv_class);
    //var mainDiv_style       = document.createAttribute('style');
    //mainDiv_style.nodeValue = 'display:none;';
    //mainDiv.setAttributeNode(mainDiv_style);
      
    // --- func insertAfter fügt bottom-Zeile in Dom-Baum ein
    this.insertAfter(this.BoxObj.bottomRefElem, mainDiv);
    this.BoxObj.boxBottom = document.getElementById(mainDiv_id.nodeValue);
    if (this.BoxObj.boxBottom) {
        // --- Inneres Div der bottom-Zeile erzeugen
        var innerDiv = document.createElement('div');
        //id für innerDiv anlegen
        var innerDiv_id       = document.createAttribute('id');
        innerDiv_id.nodeValue = 'scrollContentBottomClose_' + this.BoxObj.ScrollType + '_' + this.BoxObj.BoxId;
        innerDiv.setAttributeNode(innerDiv_id);
        //class für innerDiv anlegen
        var innerDiv_class       = document.createAttribute('class');
        innerDiv_class.nodeValue = 'tt_scrollBoxBottomClose';
        innerDiv.setAttributeNode(innerDiv_class);
        // --- Inneres Div in äußeres Div einfügen
        this.BoxObj.boxBottom.appendChild(innerDiv);
        // --- Close-Div mit onclick-Funktion belegen
        this.BoxObj.boxCloseElem = document.getElementById(innerDiv_id.nodeValue);
        this.BoxObj.boxCloseElem.onclick = function() {
            this.boxControl(this.boxObj.Elem);
        }.bind(this);
    }
}

/*
 * Definiert Werte zur Übergabe an callback-Funktion "ttsb_setBoxStatusOpen"
 */
TTScrollBox.prototype.setSocketOpen = function() {
    this.BoxObj.socketOpen.refBox       = this.BoxObj.RefBox;
    this.BoxObj.socketOpen.box          = this.BoxObj.box;
    this.BoxObj.socketOpen.boxId        = this.BoxObj.BoxId;
    this.BoxObj.socketOpen.scrollType   = this.BoxObj.ScrollType;
    this.BoxObj.socketOpen.sourceElem   = this.BoxObj.SourceElem;
    this.BoxObj.socketOpen.scrollPort   = this.BoxObj.Port;
    this.BoxObj.socketOpen.boxCloseElem = this.BoxObj.boxCloseElem;
    this.BoxObj.socketOpen.boxBottom    = this.BoxObj.boxBottom;
}

/*
 * Definiert Werte zur Übergabe an callback-Funktion "ttsb_setBoxStatusClose"
 */
TTScrollBox.prototype.setSocketClose = function() {
    this.BoxObj.socketClose.refBox       = this.BoxObj.RefBox;
    this.BoxObj.socketClose.box          = this.BoxObj.box;
    this.BoxObj.socketClose.boxId        = this.BoxObj.BoxId;
    this.BoxObj.socketClose.scrollType   = this.BoxObj.ScrollType;
    this.BoxObj.socketClose.sourceElem   = this.BoxObj.SourceElem;
    this.BoxObj.socketClose.scrollPort   = this.BoxObj.Port;
}

//Höhe der ScrollContentBox neu bestimmen
TTScrollBox.prototype.setBoxHeight = function(boxheight) {
    if (isNaN(boxheight)) {
        return false;
    }
    this.boxHeight = String(boxheight);
}

//Lade-Grafik für ScrollContentBox neu bestimmen (Format: "ajax_loader.gif")
TTScrollBox.prototype.setLoadImage = function(imgname) {
    if (imgname != '') {
        this.loadImage = String(imgname);
    }
}

//Scrolleffekt beim Öffnen der ScrollContentBox neu bestimmen
TTScrollBox.prototype.setOpenEffect = function(trim) {
    if (trim == true || trim == 1) {
        this.openEffect = true;
    } else {
        this.openEffect = false;
    }
}

//Scrolleffekt beim Schliessen der ScrollContentBox neu bestimmen
TTScrollBox.prototype.setCloseEffect = function(trim) {
    if (trim == true || trim == 1) {
        this.closeEffect = true;
    } else {
        this.closeEffect = false;
    }
}

//Scroll-Dauer beim Öffnen der ScrollContentBox neu bestimmen
TTScrollBox.prototype.setDurationOpen = function(duration) {
    if (isNaN(duration)) {
        return false;
    }
    this.durationOpen = parseInt(duration);
}

//Scroll-Dauer beim Schliessen der ScrollContentBox neu bestimmen
TTScrollBox.prototype.setDurationClose = function(duration) {
    if (isNaN(duration)) {
        return false;
    }
    this.durationClose = parseInt(duration);
}

//Scroll-Speed beim Schliessen der ScrollContentBox neu bestimmen
TTScrollBox.prototype.setStepTime = function(speed) {
    if (isNaN(speed)) {
        return false;
    }
    this.stepTime = parseInt(speed);
}

/*
 * 3 Methoden (transform, step, effect) zur Steuerung des Scrolleffektes  
 */
TTScrollBox.prototype.transform = function(from, to) {
    this.posStart  = from;
    this.posEnd    = to;
    this.startTime = (new Date()).getTime();
    this.stepper   = window.setInterval(this.step.bind(this), this.stepTime);
}

TTScrollBox.prototype.step = function() {
    var time = (new Date()).getTime();
    
    if (this.BoxObj.box) {
        //damit Scrolleffekt auch bei refreshContent sichtbar ist
        if (this.openEffect && this.boxAction == 'open' && this.BoxObj.box.style.overflow != 'hidden') {
            this.BoxObj.box.style.overflow = 'hidden';
        } else if (this.closeEffect && this.boxAction == 'close' && this.BoxObj.box.style.overflow != 'hidden') {
            this.BoxObj.box.style.overflow = 'hidden';
        }
        //Scrollprozess beenden?
        if (time >= (this.reqDuration + this.startTime)) {
            if (this.boxAction == 'open') {
                this.BoxObj.box.style.height = this.posEnd+"px";
            } else {
                this.BoxObj.box.style.height = this.posStart+"px";
            }
            //damit Scrolleffekt auch bei refreshContent sichtbar ist
            if (this.openEffect && this.BoxObj.boxStatus == 'close' && this.boxAction == 'open' && this.BoxObj.box.style.overflow != 'visible') {
                this.BoxObj.box.style.overflow = 'visible';
            }
            if (this.closeEffect && this.boxAction == 'close') {
                this.BoxObj.box.style.display = 'none';
                //ind. callback-Func?
                if (typeof(ttsb_setBoxStatusClose) == 'function') {
                    this.setSocketClose();
                    ttsb_setBoxStatusClose(this.BoxObj.socketClose);
                }
            }
            window.clearInterval(this.stepper);
            this.stepper = null;          
            //Soll eine neue Box geöffnet werden?
            if (this.closeEffect && this.boxAction == 'close' && this.procedure != 'selfClose_noOpen') {
                //alert('NEIN');
                //this.setNewBoxProcess();
                if (this.BoxStat.newId != '') {
                    this.BoxObj        = this.Boxes[this.BoxStat.newId];
                    this.BoxStat.id    = '';
                    this.BoxStat.newId = '';
                    this.BoxStat.stat  = 0;
                    //this.openEffect    = false;
                    //this.closeEffect   = false;
                    this.setBoxProcedure();
                }
            }
        } else {
            var pos     = (time - this.startTime) / (this.reqDuration);
            var posCalc = this.effect(pos) * (this.posEnd - this.posStart);
            if (this.boxAction == 'open') {
                this.BoxObj.box.style.height = String(Math.floor(posCalc + this.posStart)) + 'px';
            } else {
                this.BoxObj.box.style.height = String(Math.floor(this.posEnd - posCalc)) + 'px';
            }
        }
    }
}

TTScrollBox.prototype.effect = function(pos) {
    return ((-Math.cos(pos * Math.PI) / 2) + 0.5);
}

/*
 * Instanz aufrufen
 */
var ttScrollBox = new TTScrollBox();
