/* 
 This file was generated by Dashcode and is covered by the 
 license.txt included in the project.  You may edit this file, 
 however it is recommended to first turn off the Dashcode 
 code generator otherwise the changes will be lost.
 */

function CreateStackLayout(elementOrID, spec)
{
    var containerElement = elementOrID;
    if (elementOrID.nodeType != Node.ELEMENT_NODE) {
        containerElement = document.getElementById(elementOrID);
    }
    if (!containerElement.loaded) {
        containerElement.loaded = true;
        containerElement.object = new StackLayout(containerElement, spec);
        
        return containerElement.object;
    }
}

function StackLayout(containerElement, spec)
{
    this.element = containerElement;    
    var subviewsTransitions = spec.subviewsTransitions || [];

    // when cloning template, get style from original
    var styleElement = containerElement;
    if (spec.originalID) {
        styleElement = document.getElementById(spec.originalID);
        // get old opacity array from original stack layout
        this._viewsOldOpacity = styleElement.object._viewsOldOpacity;
    } else {
        this._viewsOldOpacity = [];
    }
    
    this._views = [];
    this._currentView = null;
    var kids = containerElement.childNodes;
    this._inDesign = window.dashcode && window.dashcode.inDesign;
    var firstElementDone = false;
    for (var i=0; i<kids.length; i++) {
        if (kids[i].nodeType == Node.ELEMENT_NODE) {
            var view = kids[i];
            this._views.push(view);
            // Doing this only during runtime since we don't want any of the settings to end up in the files during design time. Also, design time view swapping is done differently.
            if (!this._inDesign) {
                view.style.display = (firstElementDone) ? 'none' : 'block';
                // Remember the previous inline opacity because we make use of it for dissolve/fade transitions
                if (this._viewsOldOpacity.length <= i) {
                    this._viewsOldOpacity.push(view.style.opacity);
                }
                view.style.opacity = (firstElementDone) ? 0 : 1;
                firstElementDone = true;
            }
        }
    }
    
    if (this._views.length > 0) {
        this._viewsTransition = [];
        this.setCurrentView(this._views[0]);
        
        if (this._views.length == subviewsTransitions.length) {
            for (var i=0; i<this._views.length; i++) {
                this._viewsTransition[i] = CreateTransitionWithProperties(subviewsTransitions[i]);
            }
        }
    }
    
    // StackLayout is usually pretty shallow from <body>
    this._topPosFromBody = 0;
    var curElement = this.element;
    do {
        this._topPosFromBody += curElement.offsetTop;
    } while (curElement = curElement.offsetParent);
    
    this._maskContainerElement = containerElement; // default
}

StackLayout.prototype.getAllViews = function()
{
    return this._views;
}

StackLayout.prototype.getCurrentView = function()
{
    return this._currentView;
}

StackLayout.prototype.setCurrentView = function(newView, isReverse, makeTopVisible)
{
    // Look up by id if necessary
    newView = this._getView(newView);
    var oldView = this.getCurrentView();
    
    if (!newView || (oldView == newView)) {
        return;
    }
    
    // Make sure the view is ours
    if (!newView.parentNode == this.element) {
        return;
    }
    
    var transition = this._viewsTransition[this._indexOfView(newView)];
    if (!transition) transition = new Transition(Transition.NONE_TYPE);
    
    if (oldView) {
        if (isReverse) {
            transition = this._viewsTransition[this._indexOfView(oldView)];
        }
    }
    
    this._setCurrentViewPrimitive(newView, oldView, transition, isReverse, makeTopVisible);
}

StackLayout.prototype.setCurrentViewWithTransition = function(newView, transition, isReverse, makeTopVisible)
{
    // Look up by id if necessary
    newView = this._getView(newView);
    if (!newView) {
        return;
    }
    
    // Make sure the view is ours
    if (!newView.parentNode == this.element) {
        return;
    }
    var oldView = this.getCurrentView();
    
    this._setCurrentViewPrimitive(newView, oldView, transition, isReverse, makeTopVisible);
}

StackLayout.prototype.getTransitionForView = function(view)
{
    // Look up by id if necessary
    view = this._getView(view);
    return this._viewsTransition[this._indexOfView(view)];
}

StackLayout.prototype.addView = function(viewElement, transition) 
{
    this._views.push(viewElement);
    this._viewsOldOpacity.push(viewElement.style.opacity);
    viewElement.style.opacity = (this._views.length == 1 ? 1 : 0);
    viewElement.style.display = (this._views.length == 1 ? 'none' : 'block');
    viewElement.style.webkitTransform = 'translate(0px, 0px)';
    if (!transition) {
        transition = null;
        //transition = new Transition(Transition.NONE_TYPE, 0, Transition.EASE_TIMING)
    }
    this._viewsTransition[this._views.length - 1] = transition;
    this.element.appendChild(viewElement);
    
    if (this._views.length == 1) {
        this.setCurrentView(viewElement);
    }
}

StackLayout.prototype.removeView = function(viewElement) 
{
    var viewIndex = this._indexOfView(viewElement);
    if ((viewIndex < 0) || (this._views.length == 1)) {
        return;
    }
    if (viewElement == this.getCurrentView()) {
        this.setCurrentView(this._views[(viewIndex == 0 ? 1 : 0)]);
    }
    this._views.splice(viewIndex, 1);
    this._viewsOldOpacity.splice(viewIndex, 1);
    this._viewsTransition.splice(viewIndex, 1);
    this.element.removeChild(viewElement);
}

StackLayout.prototype._indexOfView = function(view)
{
    var index = -1;
    if (this._views.indexOf) {
        index = this._views.indexOf(view);
    }
    else {
        // Tiger's Dashboard doesn't have indexOf for array
        for (var i=0; i<this._views.length; i++) {
            if (this._views[i] == view) {
                index = i;
                break;
            }
        }
    }
    return index;
}

StackLayout.prototype._getView = function(view)
{
    if (view) {
        if (view.nodeType == Node.ELEMENT_NODE) {
            // Already an element
            return view;
        }
        if (view.element) {
            // It's a part object
            return view.element;
        }
        // Try it as an id
        return document.getElementById(view);
    }
    return null;
}

StackLayout.prototype._setRestrictToBrowserTransition = function(restrictFlag)
{
    this._restrictedBrowserTransition = restrictFlag ? CreateTransitionWithProperties( {'type' : Transition.PUSH_TYPE, 'direction' : Transition.RIGHT_TO_LEFT_DIRECTION, 'timing' : Transition.EASE_IN_OUT_TIMING} ) : null;
}

StackLayout.prototype._getRealTransition = function(transition)
{
    var realTransition = transition;
    if (this._restrictedBrowserTransition) {
        // Note that we are not making a copy of it, mainly for performance reason on the device.
        realTransition = this._restrictedBrowserTransition;
        realTransition.setDuration(transition.getDuration());
    }
    return realTransition;
}

StackLayout.prototype._setCurrentViewPrimitive = function(newView, oldView, transition, isReverse, makeTopVisible)
{
    // newView must be the element now and all error checking has been done.
    
    // View swapping in design time is done in application. Also, we want to be very careful about performing transition during design time because the attributes that get added during the transition into the DOM will get persisted into the HTML during regeneration.
    if (!this._inDesign) {
        if (makeTopVisible) {
            var scrollY = this._topPosFromBody - window.pageYOffset;
            if (scrollY < 0) {
                window.scrollBy(0, scrollY);
            }
        }
        
        if (transition) {
            this._restoreOldOpacity(oldView);
            this._restoreOldOpacity(newView);
            
            var realTransition = this._getRealTransition(transition);
            realTransition._maskContainerElement = this._maskContainerElement;
            realTransition.perform(newView, oldView, isReverse);
        }
        else {
            if (oldView) oldView.style.display = 'none';
            if (newView) {
                newView.style.display = 'block';
                this._restoreOldOpacity(newView);
            }
        }
    }
    
    this._currentView = newView;
}

// Restore previous inline opacity
StackLayout.prototype._restoreOldOpacity = function(view)
{
    if (view) {
        var oldOpacity = this._viewsOldOpacity[this._indexOfView(view)];
        view.style.opacity = (oldOpacity !== undefined) ? oldOpacity : null;
    }
}
