/* Copyright (c) Business Objects 2006. All rights reserved. */

/**
 * ReportAlbum Constructor
 */
bobj.crv.newReportAlbum = function(kwArgs) {
    var mb = MochiKit.Base;
    var UPDATE = mb.update;
    var BIND = mb.bind;
    var ALBUM = bobj.crv.ReportAlbum;
    
    kwArgs = UPDATE({
        id: bobj.uniqueId(),
        initTabIdx: 0, // Index of tab to select when initializing
        width: 800,
        height: 500,
        displayDrilldownTab : true
    }, kwArgs);
    
    
    // Override TabbedZone's TabBarWidget
    var tabbar = newNaviBarWidget(bobj.uniqueId(), _HorizTabTopWithClose, null, null, kwArgs.width, null, null, null, false, true, false);
    var o = newTabbedZone(kwArgs.id, tabbar, kwArgs.width, kwArgs.height);
    
    tabbar.cb = BIND(ALBUM._onSelectTab, o);
    tabbar.closeTab = BIND(ALBUM._removeView, o, true);
    bobj.fillIn(o, kwArgs);  
    o.widgetType = 'ReportAlbum';
    o._views = [];
    o._hideFrame = false;
    
    // Attach member functions 
    o.selectOld = o.select;
    UPDATE(o, ALBUM);
    
    return o;    
};

bobj.crv.ReportAlbum = {
    getTabBarHeight : function() {
        return this.tabs.getHeight ();
    },
    
    init : function() {
        /*
         * This is not nice... Copied super class' init code here so that select will be called only once.
         */
        this.tzOldInit ();
        this.tabs.init ();
        this.showDrilldownTab (this.displayDrilldownTab);

        var views = this._views;
        if (views.length > 0) {
            for ( var i = 0, len = views.length; i < len; i++) {
                /* Since views are not initializing themself (as before through
                 adding bobj.crv.getInitHtml to their HTML)
                 it is report album's responsibility to initialize its children */
                views[i].init ();

            }

            if (this.initTabIdx < 0 || this.initTabIdx >= views.length) {
                this.initTabIdx = 0;
            }

            this.select (this.initTabIdx);
        }
    },
    
    showDrilldownTab  : function (isDisplay) {
        this.displayDrilldownTab = isDisplay;
        try 
        {
            this.tabs.layer.parentNode.parentNode.style.display = isDisplay ? ( _ie ? "block" : "table-row") : "none";
        }
        catch(e){}
    },
    
    isDisplayDrilldownTab : function () {
        return this.displayDrilldownTab;
    },
    
    setHideFrame : function(hide) {
        this._hideFrame = hide;
        var selectedView = this.getSelectedView ();
        if (selectedView && this._hideFrame)
        	selectedView.hideFrame();
    },

    update : function(update) {
        if (!update || update.cons !== "bobj.crv.newReportAlbum") {
            return;
        }

        /* Updates all views */
        for ( var i = 0, len = update.children.length; i < len; i++) {
            var updateView = update.children[i];
            var view = this._views[i];
            if (view) {
                view.update (updateView); /* updates current view */
            }
        }

        var updateChildrenLength = update.children.length;
        var currentViewsLength = this._views.length;

        /* Adds any new view created by drill down action */
        if (updateChildrenLength > currentViewsLength) {
            for ( var i = currentViewsLength, len = updateChildrenLength; i < len; i++) {
                this.delayedAddChild (bobj.crv.createWidget (update.children[i]));
            }
        }
        /* Removes views that are have been removed from viewstate */
        else if (updateChildrenLength < currentViewsLength) {
            for ( var i = currentViewsLength -1, len = updateChildrenLength; i >= len; i--) {
                this._removeView (false, i); /* removes non-existing views */
            }
        }

        this.initTabIdx = update.args.initTabIdx;
        this.select (this.initTabIdx);
    },
    
    /**
     * @return index of the tab specified by viewstateid
     */
    findTabNumber : function(viewStateId) {
        var views = this._views;
        for ( var i = 0, len = views.length; i < len; i++)
            if (views[i].viewStateId == viewStateId)
                return i;

        return -1;
    },
    
    /**
     * Adds view to its list of views. Since this method can be called after initialization time, its HTML
     * is first added to report album, and then widget is intialized.
     */
    delayedAddChild : function(view) {
        this._views.push (view);
        var tab = this.tabs.add(view.label, view.tooltip);
        var tabHTML = this.getTabHTML (this._views.length - 1);
        append (getLayer (this.id + "_container"), tabHTML);
        view.init ();
    },
    
    addChild : function(view) {
        if (view) {
            this._views.push (view);
            this.add (view.label, view.tooltip);
        }
    },
    
    getHTML : function() {
        var html = this.beginHTML ();
        var children = this._views;
        for ( var i = 0, len = children.length; i < len; ++i) {
            html += this.getTabHTML (i);
        }

        html += this.endHTML ();
        return html;
    },
    

    /**
     * @param index,
     *            index of tab to create HTML for
     * @return creates HTML for tab specified by index
     */
    getTabHTML : function(index) {
        var tab = this.tabs.items[index];
        var view = this._views[index];
        html = '';

        if (tab && view) {
            html += this.beginTabHTML (tab);
            html += view.getHTML ();
            html += this.endTabHTML ();
        }

        return html;
    },
    
    /**
     * Resize the outer dimensions of the ReportAlbum. The standard resize method, inherited from TabbedZoneWidget, resizes the container. We
     * can't override it without breaking things.
     */
    resizeOuter : function(w, h) {
        var tabHeight = 33;
        var frameWidth = 10;
        
        if(bobj.isNumber (h)) {
            if(this.displayDrilldownTab)
                h -= tabHeight;
            h = Math.max(h, 0);
        }

        if(bobj.isNumber (w)) {
            if(!this._hideFrame) 
                w -= frameWidth;
            
            w = Math.max(w, 0);
        }
        

        this.resize (w, h);
        this.tabs.resize (w);

        var selectedView = this.getSelectedView ();
        if (selectedView) {
            selectedView.resize (); /* Notify ReportView of resize */
        }
    },
    
    
    
    /**
     * @return Returns a suggested size for the widget as an object with width and height integer properties that specify the dimensions in
     *         pixels.
     */
    getBestFitSize : function() {
        var w = this._hideFrame ? 0 : 10;
        var h = this.displayDrilldownTab ? 33 : 0;
        var selectedView = this.getSelectedView ();
        if (selectedView) {
            var viewSize = selectedView.getBestFitSize ();
            w += viewSize.width;
            h += viewSize.height;
        }

        return {
            width : w,
            height : h
        };
    },
    
    /**
     * Overrides parent. Opens a tab with a positioned div. The positioning prevents
     * the ReportView from disappearing in IE.
     */
    beginTabHTML : function(tab) {
        return bobj.html.openTag ('div', {
            id : tab.zoneId,
            style : {
                display : 'none',
                width : this.w + 'px',
                height : this.h + 'px',
                position : 'relative'
            }
        });
    },
    
    /**
     * @return Returns the select ReportView or null if no view is selected
     */
    getSelectedView : function() {
        return this._views[this.oldIndex];
    },
    

    /**
     * Overrides parent. Selects a report view to display.
     *
     * @param index [int]  Index of the report view
     */
    select : function(index) {
        var partial = MochiKit.Base.partial;

        if (index >= 0 && index < this._views.length && index != this.oldIndex) {

            /* Disposes currently selected view */
            var selectedView = this.getSelectedView ();
            if (selectedView) {
                selectedView.dispose ();
            }

            /* Creates new signals for newly selected view */
            var selectedView = this._views[index];

            /* Does the dirty DOM manipulation to actually change the view */
            this.selectOld (index);

            /*
             * Notifies parameter controller that view has changes so it can enable/disable panel based on view's type
             */
            MochiKit.Signal.signal (this, "viewChanged");
        }
    },
    
    /**
     * Removes view specified by index from view list
     * 
     * @param autoSelectNext
     *            [boolean] indicates whether another view should be auto selected after view specified by index is removed
     * @param index
     *            [Number} index of view that would be removed
     */
    _removeView : function(autoSelectNext, index) {
        var removedView = this._views[index];
        var removedTab = this.tabs.items[index];

        autoSelectNext = (removedTab != null && removedTab.isSelected && autoSelectNext);
        
        if (removedView) {
            removedView.dispose ();
            bobj.deleteWidget (removedView);
            MochiKit.Signal.signal (this, 'removeView', removedView);
        }
  
        if (removedTab.isSelected) {
            /* oldIndex (index of currently selected view) needs to be reset so when
             response for the next selected view arrives
             viewer think that view has changed */
             this.oldIndex = -1;
        }

        arrayRemove (this, '_views', index);
        this.tabs.remove (index, autoSelectNext);
        bobj.deleteWidget (removedTab);
    },
    
    _onSelectTab : function(index) {
        if(index != this.oldIndex)
            MochiKit.Signal.signal (this, 'selectView', this._views[index]);
    }
};

