/*jslint browser: true */
/*global Jaxer, YUI, YAHOO:true,
    getOptimalPortfolio, getKeyStatistics, getMostUsedSymbols,
    getQuotesFromYahoo, getImpliedVolatility */

"use strict";

YUI({
    'yui2': '2.8.1',
    '2in3': '3',
    'ignore': [
        'yui2-skin-sam-autocomplete',
        'yui2-skin-sam-container',
        'yui2-skin-sam-menu',
        'yui2-skin-sam-button',
        'yui2-skin-sam-calendar',
        'yui2-skin-sam-datatable',
        'yui2-skin-sam-layout',
        'yui2-skin-sam-slider',
        'yui2-skin-sam-tabview'
    ]
}).use('node-base', 'get', 'async-queue',
    'yui2-utilities',
    'yui2-datasource',
    'yui2-autocomplete',
    'yui2-container',
    'yui2-menu',
    'yui2-button',
    'yui2-calendar',
    'yui2-json',
    'yui2-swf',
    'yui2-charts',
    'yui2-cookie',
    'yui2-datatable',
    'yui2-layout',
    'yui2-slider',
    'yui2-tabview',
        function (Y) {

    YAHOO = Y.YUI2;

    YAHOO.widget.Chart.SWFURL =
        "http://yui.yahooapis.com/2.8.1/build/charts/assets/charts.swf";

    YAHOO.namespace("proplus.conpa");

    YAHOO.proplus.conpa.COOKIE = "proplus.conpa.basket";

    YAHOO.proplus.conpa.init = function () {
        var Dom = YAHOO.util.Dom,
            now, tabView_Main,
            myDataTable,
            waitPanel,
            pieChartPanel = null,
            performanceChartPanel = null,
            scriptPanel = null, scriptHandle = null,
            pieDS, pieChart, perfDS, perfChart,
            assetStatsPanel = null, assetStatsLayout = null,
            graphPanel = null,
            oGetOptimalPortfolioButton, oReferenceDateButton, nTargetReturn;

        now = new Date();
        tabView_Main = new YAHOO.widget.TabView('tab_Main');

        function labelReferenceDateButton(date) {
            return date.getDate() + " " +
                YAHOO.widget.Calendar.DEFAULT_CONFIG.MONTHS_SHORT
                    .value[date.getMonth()] + " " +
                date.getFullYear();
        }

        function resetOptimalWeigths(dt) {
            var i, products, nProducts, record, recordData;

            products = dt.getRecordSet();
            nProducts = products.getLength();
            for (i = 0; i < nProducts; i = i + 1) {
                record = products.getRecord(i);
                recordData = record.getData();
                recordData.optimalWeight = 0;
                dt.updateRow(record, recordData);
            }
            if (pieChartPanel !== null) {
                pieChartPanel.hide();
            }
            if (performanceChartPanel !== null) {
                performanceChartPanel.hide();
            }

            if (assetStatsPanel !== null) {
                assetStatsPanel.hide();
            }
            if (scriptPanel !== null) {
                scriptPanel.hide();
            }
            if (scriptHandle !== null) {
                Y.detach(scriptHandle);
            }

        }

        function initPanels() {
            var panel,
                helpPanel, helpHeader = "Help",
                helpBody = "<iframe src='docs/ConPA_help.html' width='100%' height='100%' frameborder='0'/>";

            panel = new YAHOO.widget.SimpleDialog('alert', {
                fixedcenter: true,
                visible: false,
                modal: true,
                width: '256px',
                constraintoviewport: true,
                icon: YAHOO.widget.SimpleDialog.ICON_WARN,
                buttons: [{
                    text: 'OK',
                    handler: function () {
                        panel.hide();
                    },
                    isDefault: true
                }]
            });
            panel.setHeader('Alert');
            panel.setBody('Notta');
            panel.render("body");

            YAHOO.proplus.conpa.alert = function (str) {
                var kl_27 = new YAHOO.util.KeyListener("body", {
                    keys: 27
                }, {
                    fn: panel.hide,
                    scope: panel,
                    correctScope: true
                });
                kl_27.enable();

                panel.setBody(str);
                panel.cfg.setProperty('icon', YAHOO.widget.SimpleDialog.ICON_WARN);
                panel.bringToTop();
                panel.show();
            };

            waitPanel = new YAHOO.widget.Panel("waitPanel", {
                width: "240px",
                fixedcenter: true,
                close: false,
                draggable: false,
                zIndex: 10000,
                modal: true,
                visible: false
            });
            waitPanel.setHeader("Please wait...");
            waitPanel.setBody("<img width= \"220\" height=\"19\" " +
                "src=\"images/rel_interstitial_loading.gif\"/>");
            waitPanel.render("body");

            helpPanel = new YAHOO.widget.Panel("helpPanel", {
                visible: false,
                constraintoviewport: true,
                draggable: true,
                close: true,
                fixedcenter: true,
                width: '400px',
                height: '500px',
                zIndex: 99
            });
            helpPanel.setHeader(helpHeader);
            helpPanel.setBody(helpBody);
            helpPanel.setFooter("");
            helpPanel.render(Dom.get('bd'));

            YAHOO.util.Event.addListener("help", "click", function () {
                helpPanel.setBody(helpBody);
                helpPanel.bringToTop();
                helpPanel.show();
            });

            scriptPanel = new YAHOO.widget.Panel("scriptPanel", {
                visible: false,
                modal: false,
                constraintoviewport: true,
                draggable: true,
                close: true,
                fixedcenter: true,
                width: '512px',
                height: '394px'
            });
            scriptPanel.setHeader("R Script");
            scriptPanel.setBody("");
            scriptPanel.setFooter("");
            scriptPanel.render(Dom.get('bd'));

            Y.on("click", function () {
                var scriptRMsg = "#R Script is empty.<br />" +
                    "#Firstly you should get an optimal portfolio.<br />";

                scriptPanel.setBody(scriptRMsg);
                scriptPanel.bringToTop();
                scriptPanel.show();
            }, "#getRScript");
        }

        function createPieChart() {
            if (pieChartPanel !== null) {
                pieChartPanel.hide();
                pieChartPanel.destroy();
            }

            pieChartPanel = new YAHOO.widget.Panel("pieChartPanel", {
                width: "256px",
                fixedcenter: false,
                x: Dom.getXY('tab_Advisory')[0] + 10 + 450,
                y: 300,
                constraintoviewport: true,
                close: true,
                dragOnly: true,
                modal: false,
                visible: false
            });

            pieChartPanel.setHeader("Optimal Portfolio Pie");
            pieChartPanel.setBody("<div id=\"pieChart\" style=\"height:200px\">Unable to load Flash content. The YUI Charts Control requires Flash Player 9.0.45 or higher. You can install the latest version at the <a href=\"http://www.adobe.com/go/getflashplayer\">Adobe Flash Player Download Center</a>.</p></div>");
            pieChartPanel.render("tab_Advisory");

            pieDS = new YAHOO.util.DataSource([]);
            pieDS.responseType = YAHOO.util.DataSource.TYPE_JSARRAY;
            pieDS.dataType = YAHOO.util.DataSource.TYPE_JSARRAY;
            pieDS.responseSchema = {
                fields: ["asset", "weigth"]
            };

            YAHOO.proplus.conpa.getDataTipTextPie = function (item, index, series) {
                var toolTipText = item.asset;

                toolTipText = toolTipText + "\n" +
                YAHOO.util.Number.format(item.weigth * 100, {
                    suffix: "%",
                    thousandsSeparator: ",",
                    decimalPlaces: 2
                });
                return toolTipText;
            };

            pieChart = new YAHOO.widget.PieChart("pieChart", pieDS, {
                dataField: "weigth",
                categoryField: "asset",
                style: {
                    padding: 20,
                    legend: {
                        display: "right",
                        padding: 10,
                        spacing: 5,
                        font: {
                            family: "Arial",
                            size: 9
                        }
                    }
                },
                dataTipFunction: YAHOO.proplus.conpa.getDataTipTextPie,
                expressInstall: "assets/expressinstall.swf",
                wmode: "opaque"
            });
        }

        function createPerformanceChart() {
            var perfSeriesDef, perfTimeAxis;

            if (performanceChartPanel !== null) {
                performanceChartPanel.hide();
                performanceChartPanel.destroy();
            }

            performanceChartPanel = new YAHOO.widget.Panel("performanceChartPanel", {
                width: "400px",
                fixedcenter: false,
                x: Dom.getXY('tab_Advisory')[0] + 10,
                y: 300,
                constraintoviewport: true,
                close: true,
                dragOnly: true,
                modal: false,
                visible: false
            });

            performanceChartPanel.setHeader("Optimal Portfolio Performance");
            performanceChartPanel.setBody("<div id=\"performanceChart\" style=\"height:200px\">Unable to load Flash content. The YUI Charts Control requires Flash Player 9.0.45 or higher. You can install the latest version at the <a href=\"http://www.adobe.com/go/getflashplayer\">Adobe Flash Player Download Center</a>.</p></div>");
            performanceChartPanel.render("tab_Advisory");

            perfDS = new YAHOO.util.DataSource([]);
            perfDS.responseType = YAHOO.util.DataSource.TYPE_JSARRAY;
            perfDS.dataType = YAHOO.util.DataSource.TYPE_JSARRAY;
            perfDS.responseSchema = {
                fields: ["performance", "week"]
            };

            perfSeriesDef = [{
                displayName: "Performance",
                yField: "performance"
            }];

            YAHOO.proplus.conpa.formatTimeData = function (value, major) {
                var arr = value.toString().split(" ");
                return arr[1];
            };

            perfTimeAxis = new YAHOO.widget.TimeAxis();
            perfTimeAxis.labelFunction = YAHOO.proplus.conpa.formatTimeData;
            perfTimeAxis.majorTimeUnit = "month";

            YAHOO.proplus.conpa.getDataTipTextPerf = function (item, index, series) {
                var toolTipText = labelReferenceDateButton(item.week);

                toolTipText = toolTipText + "\n" +
                    YAHOO.util.Number.format(item[series.yField], {
                        suffix: "%",
                        thousandsSeparator: ",",
                        decimalPlaces: 2
                    });

                return toolTipText;
            };

            perfChart = new YAHOO.widget.LineChart("performanceChart", perfDS, {
                xField: "week",
                xAxis: perfTimeAxis,
                series: perfSeriesDef,
                dataTipFunction: YAHOO.proplus.conpa.getDataTipTextPerf,
                expressInstall: "assets/expressinstall.swf",
                wmode: "opaque"
            });
        }

        function initAssetSearch() {
            var sUri = "http://d.yimg.com/aq/autoc", oDS, oAC;

            oDS = new YAHOO.util.ScriptNodeDataSource(sUri);
            oDS.responseSchema = {
                resultsList: "ResultSet.Result",
                fields: ["symbol", "name", "exch", "type", "exchDisp"]
            };

            oDS.generateRequestCallback = function (id) {
                YAHOO.util.ScriptNodeDataSource.callbacks =
                    YAHOO.util.ScriptNodeDataSource.callbacks[id];
                return "&" + this.scriptCallbackParam +
                    "=YAHOO.util.ScriptNodeDataSource.callbacks";
            };

            oAC = new YAHOO.widget.AutoComplete("ysearchinput",
                "ysearchcontainer", oDS);
            oAC.useShadow = true;
            oAC.useIFrame = true;

            oAC.generateRequest = function (sQuery) {
                return "?region=US&lang=en-US&query=" + sQuery;
            };
            oAC.formatResult = function (oResultItem, sQuery) {
                return oResultItem[0] +
                    " " + oResultItem[1] +
                    " (" + oResultItem[3] +
                    " - " + oResultItem[4] + ")";
            };
            oAC.doBeforeExpandContainer = function (oTextbox,
                oContainer, sQuery, aResults) {
                var pos = Dom.getXY(oTextbox);
                pos[1] += Dom.get(oTextbox).offsetHeight + 2;
                Dom.setXY(oContainer, pos);
                return true;
            };
            oAC.itemSelectEvent.subscribe(function (type, args) {
                var data = {};

                data.symbol = args[2][0];
                data.name = args[2][1];
                data.type = args[2][3];
                data.exchDisp = args[2][4];
                data.optimalWeight = 0;
                data.min = 0;
                data.max = 100;

                myDataTable.addRow(data);

                resetOptimalWeigths(myDataTable);

                oReferenceDateButton.set("label",
                    labelReferenceDateButton(now));
                oReferenceDateButton.date = now;

                Jaxer.Callback.onfailureAsync = function (error, extra, xhr) {
                    // we can continue the game without prices in the cache
                };
                Jaxer.Callback.ontimeoutAsync = function (error, extra, xhr) {
                    // we can continue the game without prices in the cache
                };

                getQuotesFromYahoo.async(function (response) {
                  // we don't deal with the response, because the aim is putting
                  // the prices of the symbol in the cache.
                }, data.symbol, oReferenceDateButton.date);
            });

            function initMostUsedSymbols() {
                var oMenuSymbolsButton;

                try {
                    Jaxer.Callback.onfailureAsync = function (error, extra, xhr) {
                        // we can continue the game without mostUsedSymbols
                    };
                    Jaxer.Callback.ontimeoutAsync = function (error, extra, xhr) {
                        // we can continue the game without mostUsedSymbols
                    };

                    getMostUsedSymbols.async(function (mostUsedSymbols) {
                        var i, symbols = [];

                        function onMenuSymbolClick(p_sType, p_aArgs) {
                            var oMenuItem = p_aArgs[1].cfg.getProperty("text");

                            Dom.get("ysearchinput").value = oMenuItem;
                            setTimeout(function () {
                                oAC.getInputEl().focus();
                                oAC.sendQuery(oMenuItem);
                            }, 0);
                        }

                        for (i = 0; i < mostUsedSymbols.length; i = i + 1) {
                            symbols.push({
                                text: mostUsedSymbols[i][0], // symbol
                                value: mostUsedSymbols[i][1] // usage
                            });
                        }
                        oMenuSymbolsButton = new YAHOO.widget.Button(
                            "mostUsedSymbols", {
                            type: "menu",
                            menu: symbols
                        });

                        oMenuSymbolsButton.getMenu()
                            .subscribe("click", onMenuSymbolClick);
                    });
                } catch (e) {
                    // we can continue the game without mostUsedSymbols
                }
            }

            initMostUsedSymbols();
        }

        function initBasketDataTable() {
            var myColumnDefs, myDataSource, keyStats = [], volStats = [];

            myColumnDefs = [
                {
                    key: "remove",
                    label: "",
                    formatter: function (el, oRecord, oColumn, oData) {
                        el.innerHTML = "<img width=\"16\" height=\"16\" " +
                            "src=\"images/cancel.png\"/>";

                        el.style.cursor = 'pointer';
                    }
                },
                {
                    key: "symbol",
                    label: "Symbol",
                    formatter: function (el, oRecord, oColumn, oData) {
                        el.innerHTML = oData;
                        el.title = oRecord.getData('name');
                        el.style.cursor = 'pointer';
                    },
                    sortable: true
                },
                {
                    key: "name",
                    label: "Name",
                    width: 256,
                    sortable: true
                },
                {key: "type", label: "T", sortable: true},
                {key: "exchDisp", label: "Market", sortable: true},
                {
                    key: "optimalWeight",
                    label: "O W %",
                    width: 48,
                    formatter: function (el, oRecord, oColumn, oData) {
                        if (!isNaN(oData)) {
                            oData = oData * 100;
                            el.innerHTML = YAHOO.util.Number.format(oData, {
                                prefix: "",
                                decimalPlaces: 2,
                                decimalSeparator: ".",
                                thousandsSeparator: ","
                            });
                            el.align = "right";
                        }
                    },
                    sortable: true
                },
                {
                    key: "min",
                    label: "Min %",
                    width: 48,
                    formatter: function (el, oRecord, oColumn, oData) {
                        if (isNaN(oData) || oData < 0) {
                            oData = 0;
                        }
                        if (oData > 100) {
                            oData = 100;
                        }
                        el.innerHTML = YAHOO.util.Number.format(oData, {
                            prefix: "",
                            decimalPlaces: 2,
                            decimalSeparator: ".",
                            thousandsSeparator: ","
                        });
                        el.align = "right";

                        if (oData > 0) {
                            el.style.backgroundColor = "#FFA0A0";
                        } else {
                            el.style.backgroundColor = "#FFFFFF";
                        }
                    },
                    sortable: true,
                    editor: "textbox",
                    editorOptions: {
                        disableBtns: true,
                        validator: function (newData, oldData) {
                            if (newData !== oldData) {
                                YAHOO.widget.DataTable.validateNumber(newData);
                            }
                            return newData;
                        }
                    }
                },
                {
                    key: "max",
                    label: "Max %",
                    width: 48,
                    formatter: function (el, oRecord, oColumn, oData) {
                        if (isNaN(oData) || oData > 100) {
                            oData = 100;
                        }
                        if (oData < 0) {
                            oData = 0;
                        }
                        el.innerHTML = YAHOO.util.Number.format(oData, {
                            prefix: "",
                            decimalPlaces: 2,
                            decimalSeparator: ".",
                            thousandsSeparator: ","
                        });
                        el.align = "right";
                        if (oData < 100) {
                            el.style.backgroundColor = "#FFA0A0";
                        } else {
                            el.style.backgroundColor = "#FFFFFF";
                        }
                    },
                    sortable: true,
                    editor: "textbox",
                    editorOptions: {
                        disableBtns: true,
                        validator: function (newData, oldData) {
                            if (newData !== oldData) {
                                YAHOO.widget.DataTable.validateNumber(newData);
                            }
                            return newData;
                        }
                    }
                }
            ];

            myDataSource = new YAHOO.util.DataSource([]);
            myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSARRAY;
            myDataSource.responseSchema = {
                fields: ["symbol", "name", "type", "exchDisp"]
            };

            myDataTable = new YAHOO.widget.DataTable("basket",
                myColumnDefs, myDataSource, {
                caption: "",
                selectionMode: "single"
            });


            myDataTable.subscribe("cellMouseoutEvent", function (oArgs) {
                graphPanel.hide();
            });

            myDataTable.subscribe("cellMouseoverEvent", function (oArgs) {
                var column, firstChar, graphUrl, imgTag, record, symbol, target;

                target = oArgs.target;
                column = this.getColumn(target);

                if (column.key === "name") {
                    record = this.getRecord(target);
                    symbol = record.getData("symbol").toLowerCase();
                    graphUrl = "http://chart.finance.yahoo.com/c/bb/";
                    firstChar = symbol.substr(0, 1);
                    if (firstChar === "^") {
                        firstChar = "_";
                    }
                    firstChar.toLowerCase();
                    imgTag = "<img src=\"" + graphUrl + firstChar + "/" +
                        symbol + "\" width=\"192\" height=\"96\" alt=\"" +
                        symbol + "\">";

                    if (graphPanel !== null) {
                        graphPanel.destroy();
                    }

                    graphPanel = new YAHOO.widget.Panel("graphPanel", {
                        context: [this.getTdEl(target), "tl", "br"],
                        fixedcenter: false,
                        close: false,
                        draggable: false,
                        modal: false,
                        visible: false
                    });
                    graphPanel.setBody(imgTag);
                    graphPanel.render("tab_Advisory");
                    graphPanel.show();
                }
            });

            myDataTable.subscribe("cellClickEvent", function (ev) {
                var target, column, symbol, type,
                    callLineDS, callLineChart, callSeriesDef,
                    putLineDS, putLineChart, putSeriesDef;

                target = ev.target;
                column = this.getColumn(target);

                if (column.key === "remove") {
                    if (this.getRecordSet().getLength() > 0) {

                        this.deleteRow(this.getRecord(target));
                        resetOptimalWeigths(this);

                        oReferenceDateButton.set("label",
                            labelReferenceDateButton(now));
                        oReferenceDateButton.date = now;
                    }
                }

                function exitGetKeyStatistics() {
                    var i, stats = "", el;

                    waitPanel.hide();

                    if (keyStats[symbol] !== undefined) {
                        for (i = 0; i < keyStats[symbol].length; i = i + 1) {
                            stats += "<div class=\"label\">" +
                                keyStats[symbol][i].inputParams.label +
                                "<\/div>";
                            stats += "<div class=\"value\">" +
                                keyStats[symbol][i].inputParams.value +
                                "<\/div>";
                        }
                        el = Dom.get('formKeyStatistics');
                        el.innerHTML = stats;
                    } else {
                        el = Dom.get('formKeyStatistics');
                        el.innerHTML = "Key Statistics not available for " + symbol;
                    }

                    function exitGetImpliedVolatility() {
                        var vol = volStats[symbol];

                        callLineDS.liveData = vol.callVolatility;
                        callLineChart.set('dataSource', callLineDS);
                        putLineDS.liveData = vol.putVolatility;
                        putLineChart.set('dataSource', putLineDS);
                        el = Dom.get('impliedVolHeader');
                        el.innerHTML = "<b>Call and Put Implied Volatilty for " +
                            symbol + "<br />" +
                            " strike " + vol.strike + " - " +
                            " riskfree " + vol.riskFree * 100 + "% 3 months - " +
                            " expire at close " + vol.expDate +
                            "</b>";
                        Dom.setStyle('loading', 'display', 'none');
                        Dom.setStyle('putVolChart', 'display', 'block');
                        Dom.setStyle('callVolChart', 'display', 'block');
                    }

                    if (volStats[symbol] === undefined) {
                        getImpliedVolatility.async(function (res) {
                            volStats[symbol] = res;
                            if (volStats[symbol].callVolatility.length === 0) {
                                delete volStats[symbol];
                                Dom.setStyle('loading', 'display', 'none');
                                el = Dom.get('callVolChart');
                                el.innerHTML = "Vol Statistics not available for " + symbol;
                                el = Dom.get('putVolChart');
                                el.innerHTML = "Vol Statistics not available for " + symbol;
                                Dom.setStyle('putVolChart', 'display', 'block');
                                Dom.setStyle('callVolChart', 'display', 'block');
                            } else {
                                exitGetImpliedVolatility();
                            }
                        }, symbol);
                    } else {
                        exitGetImpliedVolatility();
                    }

                    assetStatsPanel.bringToTop();
                    assetStatsPanel.show();
                }

                if (column.key === "symbol") {
                    symbol = this.getRecord(target).getData("symbol");
                    type = this.getRecord(target).getData("type");

                    if (type !== "S") {
                        YAHOO.proplus.conpa.alert("Key Statistics not available for " + symbol);
                        return;
                    }

                    if (assetStatsPanel !== null) {
                        assetStatsLayout.destroy();
                        assetStatsPanel.destroy();
                    }

                    assetStatsPanel = new YAHOO.widget.Panel('assetStatsPanel', {
                        x: 400,
                        y: 290,
                        width: "825px",
                        height: "460px",
                        constraintoviewport: true,

                        fixedcenter: false,
                        visible: false
                    });
                    assetStatsPanel.setHeader("Key Statistics for " + symbol);
                    assetStatsPanel.setBody("<div id='layoutKeyStatistics'></div>");
                    assetStatsPanel.render("tab_Advisory");

                    assetStatsLayout = new YAHOO.widget.Layout('layoutKeyStatistics', {
                        height: (assetStatsPanel.body.offsetHeight - 20),
                        units: [{
                            position: 'left',
                            width: 290,
                            body: "<div id='formKeyStatistics'></div>",
                            gutter: '1'
                        },
                        {
                            position: 'center',
                            width: 535,
                            body: "<div id=\"impliedVolHeader\"></div>" +
                                "<div id=\"loading\"><b>Calculating implied volatility...</b><br /><img width= \"220\" height=\"19\" src=\"images/rel_interstitial_loading.gif\" /></div>" +
                                "<div id=\"callVolChart\" style=\"height:200px\">Unable to load Flash content. The YUI Charts Control requires Flash Player 9.0.45 or higher. You can install the latest version at the <a href=\"http://www.adobe.com/go/getflashplayer\">Adobe Flash Player Download Center<\/a>.<\/p><\/div>" +
                                "<div id=\"putVolChart\" style=\"height:200px\">Unable to load Flash content. The YUI Charts Control requires Flash Player 9.0.45 or higher. You can install the latest version at the <a href=\"http://www.adobe.com/go/getflashplayer\">Adobe Flash Player Download Center<\/a>.<\/p><\/div>",
                            gutter: '1'
                        }]
                    });
                    assetStatsLayout.render();
                    Dom.setStyle('putVolChart', 'display', 'none');
                    Dom.setStyle('callVolChart', 'display', 'none');

                    YAHOO.proplus.conpa.getDataTipTextLine = function (item, index, series) {
                        var toolTipText = "strike: " + item.strike +
                            " - ask: " +
                            (item.ask ? YAHOO.util.Number.format(item.ask, {
                                decimalPlaces: 2
                            }) : "N/A") +
                            " - bid: " +
                            (item.bid ? YAHOO.util.Number.format(item.bid, {
                                decimalPlaces: 2
                            }) : "N/A");

                        return toolTipText;
                    };

                    callLineDS = new YAHOO.util.DataSource([]);
                    callLineDS.responseType = YAHOO.util.DataSource.TYPE_JSARRAY;
                    callLineDS.dataType = YAHOO.util.DataSource.TYPE_JSARRAY;
                    callLineDS.responseSchema = {
                        fields: ["strike", "ask", "bid"]
                    };

                    callSeriesDef = [
                        { displayName: "Ask Call Vol", yField: "ask" },
                        { displayName: "Bid Call Vol", yField: "bid" }
                    ];

                    callLineChart = new YAHOO.widget.LineChart("callVolChart", callLineDS, {
                        xField: "strike",
                        series: callSeriesDef,
                        style: {
                            xAxis: {
                                majorTicks: {
                                    display: "inside",
                                    length: 3,
                                    size: 1
                                },
                                minorTicks: {
                                    display: "inside",
                                    length: 2
                                },
                                labelRotation: -45
                            },
                            padding: 20,
                            legend: {
                                display: "right",
                                padding: 10,
                                spacing: 5,
                                font: {
                                    family: "Arial",
                                    size: 9
                                }
                            }
                        },
                        dataTipFunction: YAHOO.proplus.conpa.getDataTipTextLine,
                        expressInstall: "assets/expressinstall.swf",
                        wmode: "opaque"
                    });

                    putLineDS = new YAHOO.util.DataSource([]);
                    putLineDS.responseType = YAHOO.util.DataSource.TYPE_JSARRAY;
                    putLineDS.dataType = YAHOO.util.DataSource.TYPE_JSARRAY;
                    putLineDS.responseSchema = {
                        fields: ["strike", "ask", "bid"]
                    };

                    putSeriesDef = [
                        { displayName: "Ask Put Vol", yField: "ask" },
                        { displayName: "Bid Put Vol", yField: "bid" }
                    ];

                    putLineChart = new YAHOO.widget.LineChart("putVolChart", putLineDS, {
                        xField: "strike",
                        series: putSeriesDef,
                        style: {
                            xAxis: {
                                majorTicks: {
                                    display: "inside",
                                    length: 3,
                                    size: 1
                                },
                                minorTicks: {
                                    display: "inside",
                                    length: 2
                                },
                                labelRotation: -45
                            },
                            padding: 20,
                            legend: {
                                display: "right",
                                padding: 10,
                                spacing: 5,
                                font: {
                                    family: "Arial",
                                    size: 9
                                }
                            }
                        },
                        dataTipFunction: YAHOO.proplus.conpa.getDataTipTextLine,
                        expressInstall: "assets/expressinstall.swf",
                        wmode: "opaque"
                    });

                    waitPanel.setHeader("Retrieving Key Statistics...");
                    waitPanel.show();

                    Jaxer.Callback.onfailureAsync = function (error, extra, xhr) {
                        waitPanel.hide();
                        Dom.setStyle('loading', 'display', 'none');
                        YAHOO.proplus.conpa.alert(extra.functionName + ": failed");
                    };
                    Jaxer.Callback.ontimeoutAsync = function (error, extra, xhr) {
                        waitPanel.hide();
                        Dom.setStyle('loading', 'display', 'none');
                        YAHOO.proplus.conpa.alert(extra.functionName + ": timed out");
                    };

                    if (keyStats[symbol] === undefined) {
                        getKeyStatistics.async(function (res) {
                            keyStats[symbol] = res;
                            if (keyStats[symbol].length === 0) {
                                delete keyStats[symbol];
                            }
                            exitGetKeyStatistics();
                        }, symbol);
                    } else {
                        exitGetKeyStatistics();
                    }
                }
                this.onEventShowCellEditor(ev);
            });

            myDataTable.subscribe("editorSaveEvent", function (oArgs) {
                resetOptimalWeigths(this);
                this.saveCellEditor();
            });
        }

        function getRScriptClick(e, assets, refDate,
                                    targetReturn, targetReturnA, lows, highs) {
            var refDateStr =  refDate.getFullYear() + "-" +
                    (refDate.getMonth() + 1) + "-" + refDate.getDate(),
                refDate2YA = YAHOO.widget.DateMath.add(refDate,
                    YAHOO.widget.DateMath.YEAR, -2),
                refDate2YAStr =  refDate2YA.getFullYear() + "-" +
                    (refDate2YA.getMonth() + 1) + "-" + refDate2YA.getDate(),
                targetReturnStr = targetReturn ? targetReturn : "mean(x)",
                asset, i, n = assets.length,
                rScript = "# COPY & PASTE IN R CONSOLE<br /><br />",
                rRequire = 'require(tseries)<br /><br />',
                rHackZeroes = "hackZeroes <- function (x) {<br />" +
                        "    for (i in which(x == 0)) {<br />" +
                        "        if (i == 1) {<br />" +
                        "            c = i<br />" +
                        "            while (x[c] == 0) {<br />" +
                        "                c = c + 1<br />" +
                        "            }<br />" +
                        "            x[i] <- x[c]<br />" +
                        "        } else {<br />" +
                        "            x[i] <- x[i - 1]<br />" +
                        "        }<br />" +
                        "    }<br />" +
                        "    x<br />" +
                        "}<br /><br />",
                rInit = 'x <- c()<br /><br />',
                rReturns = '{ASSET} <- coredata(get.hist.quote(\"{SYMBOL}\", ' +
                                'start=\"{STARTDATE}\", end=\"{ENDDATE}\", ' +
                                'compression=\"w\", quote=\"Close\"))<br />' +
                    '{ASSET} <- hackZeroes({ASSET})<br />' +
                    '{ASSET}.rets <- ' +
                    'diff(log({ASSET}[1:(length({ASSET})-1)]))<br />' +
                    'x <- cbind(x, {ASSET}.rets)<br /><br />',
                lowsStr, highsStr, rRes;

            lowsStr = 'reslow = c(';
            for (i = 0; i < lows.length; i = i + 1) {
                if ((i + 1) === lows.length) {
                    lowsStr += lows[i];
                } else {
                    lowsStr += lows[i] + ', ';
                }
            }
            lowsStr += '), ';
            highsStr = 'reshigh = c(';
            for (i = 0; i < highs.length; i = i + 1) {
                if ((i + 1) === highs.length) {
                    highsStr += (highs[i] * -1);
                } else {
                    highsStr += (highs[i] * -1) + ', ';
                }
            }
            highsStr += ')';

            rRes = '#Target Return (pm) is weekly<br />';
            rRes += 'res <- portfolio.optim(x, pm = ' + targetReturnStr +
                                ", " + lowsStr + highsStr +
                                ')<br />' + 'res$pw<br /><br />';

            rScript += '<pre>' + rRequire;
            rScript += rHackZeroes;
            rScript += rInit;
            for (i = 0; i < n; i = i + 1) {
                asset = assets[i]
                    .replace("=", "_").replace("^", "i_").toLowerCase();
                rScript += "#Asset " + assets[i] + " with weekly returns<br />";
                rScript += YAHOO.lang.substitute(rReturns, {
                    ASSET: asset,
                    SYMBOL: assets[i],
                    STARTDATE: refDate2YAStr,
                    ENDDATE: refDateStr
                });
            }
            rScript += rRes + '</pre>';

            scriptPanel.setBody(rScript);
            scriptPanel.render("tab_Advisory");
            scriptPanel.show();
        }

        function initGetOptimalPortfolio()  {
            var referenceDate;

            oGetOptimalPortfolioButton = new YAHOO.widget.Button("getOptimalPortfolio");

            function onGetOptimalPortfolioClick() {
                var i, products, nProducts, record, recordData,
                    prods = [], lows = [], highs = [],
                    targetReturn, perfData = [], pieData = [];

                products = myDataTable.getRecordSet();
                nProducts = products.getLength();
                if (nProducts < 3) {
                    YAHOO.proplus.conpa.alert('You need at least 3 assets.');
                    return;
                }
                if (nProducts > 10) {
                    YAHOO.proplus.conpa.alert('You can insert maximum 10 assets.');
                    return;
                }

                for (i = 0; i < nProducts; i = i + 1) {
                    prods[i] = products.getRecord(i).getData("symbol");
                    lows[i] = products.getRecord(i).getData("min") / 100;
                    highs[i] = -products.getRecord(i).getData("max") / 100;
                }

                if (nTargetReturn !== 0) { // from annual to weekly
                    targetReturn = Math.pow((nTargetReturn + 1), (1 / 52)) - 1;
                }

                referenceDate = oReferenceDateButton.date;

                scriptPanel.hide();
                if (scriptHandle !== null) {
                    Y.detach(scriptHandle);
                }
                scriptHandle = Y.on("click", getRScriptClick, "#getRScript",
                    this,
                    prods,
                    referenceDate,
                    targetReturn,
                    nTargetReturn,
                    lows,
                    highs);

                waitPanel.setHeader("Optimizing portfolio...");
                waitPanel.show();
                oGetOptimalPortfolioButton.set("disabled", true);

                function exitGetOptimalPortfolio() {
                    oGetOptimalPortfolioButton.set("disabled", false);
                    waitPanel.hide();
                }

                Jaxer.Callback.onfailureAsync = function (error, extra, xhr) {
                    exitGetOptimalPortfolio();
                    YAHOO.proplus.conpa.alert(extra.functionName + ": failed");
                };
                Jaxer.Callback.ontimeoutAsync = function (error, extra, xhr) {
                    exitGetOptimalPortfolio();
                    YAHOO.proplus.conpa.alert(extra.functionName + ": timed out");
                };

                getOptimalPortfolio.async(function (res) {
                    try {
                        if (res.message !== "") {
                            throw res.message;
                        }

                        for (i = 0; i < nProducts; i = i + 1) {
                            record = products.getRecord(i);
                            recordData = record.getData();
                            recordData.optimalWeight = res.optim.solution[i];
                            myDataTable.updateRow(record, recordData);

                            pieData[i] = {
                                asset: prods[i],
                                weigth: res.optim.solution[i]
                            };

                            YAHOO.util.Cookie.setSubs(YAHOO.proplus.conpa.COOKIE + "." +
                                recordData.symbol, recordData, {
                                    expires: YAHOO.widget.DateMath.add(new Date(),
                                        YAHOO.widget.DateMath.DAY, 30)
                                });
                        }

                        YAHOO.util.Cookie.set(YAHOO.proplus.conpa.COOKIE +
                            ".targetReturn", nTargetReturn, {
                                expires: YAHOO.widget.DateMath.add(new Date(),
                                    YAHOO.widget.DateMath.DAY, 30)
                            });
                        YAHOO.util.Cookie.set(YAHOO.proplus.conpa.COOKIE +
                            ".referenceDate", referenceDate, {
                                expires: YAHOO.widget.DateMath.add(new Date(),
                                    YAHOO.widget.DateMath.DAY, 30)
                            });
                        YAHOO.util.Cookie.set(YAHOO.proplus.conpa.COOKIE, prods, {
                            expires: YAHOO.widget.DateMath.add(new Date(),
                                YAHOO.widget.DateMath.DAY, 30)
                        });

                        createPieChart();
                        pieDS.liveData = pieData;
                        pieChart.set('dataSource', pieDS);
                        pieChartPanel.show();

                        if (res.perf.length > 0) {
                            perfData[0] = {
                                performance: 0,
                                week: referenceDate
                            };
                            for (i = 0; i < res.perf.length; i = i + 1) {
                                perfData[i + 1] = {
                                    performance: res.perf[i] * 100,
                                    week: YAHOO.widget.DateMath.add(referenceDate,
                                            YAHOO.widget.DateMath.WEEK, i + 1)
                                };
                            }
                            createPerformanceChart();
                            perfDS.liveData = perfData;
                            perfChart.set('dataSource', perfDS);
                            performanceChartPanel.show();
                        }

                    } catch (e) {
                        YAHOO.proplus.conpa.alert(e);
                    }

                    exitGetOptimalPortfolio();
                }, prods, referenceDate.toString(), targetReturn, lows, highs);
            }

            oGetOptimalPortfolioButton.on("click", onGetOptimalPortfolioClick);
        }

        function initReferenceDate() {
            var oCalendarMenu = new YAHOO.widget.Overlay("calendarmenu", {
                visible: false,
                zIndex: 4
            });

            oReferenceDateButton = new YAHOO.widget.Button({
                type: "menu",
                id: "calendarpicker",
                label: labelReferenceDateButton(now),
                menu: oCalendarMenu,
                container: "referenceDate"
            });
            oReferenceDateButton.date = now;

            oReferenceDateButton.on("appendTo", function () {
                oCalendarMenu.setBody("&#32;");
                oCalendarMenu.body.id = "calendarcontainer";
                oCalendarMenu.render(this.get("container"));
            });

            function onReferenceDateButtonClick() {
                var maxdate, mindate, oCalendar, sMinDate, sMaxDate;

                oCalendar = new YAHOO.widget.Calendar("buttoncalendar", oCalendarMenu.body.id);

                mindate = YAHOO.widget.DateMath.add(now, YAHOO.widget.DateMath.YEAR, -2);
                maxdate = YAHOO.widget.DateMath.add(now, YAHOO.widget.DateMath.MONTH, 0);
                sMinDate = (mindate.getMonth() + 1) + "/" +
                    mindate.getDate() +
                    "/" +
                    mindate.getFullYear();
                sMaxDate = (maxdate.getMonth() + 1) + "/" +
                    maxdate.getDate() +
                    "/" +
                    maxdate.getFullYear();
                oCalendar.cfg.setProperty("mindate", sMinDate);
                oCalendar.cfg.setProperty("maxdate", sMaxDate);
                oCalendar.cfg.setProperty("navigator", true);

                oCalendar.render();

                oCalendar.selectEvent.subscribe(function (p_sType, p_aArgs) {
                    var aDate, nMonth, nDay, nYear;

                    if (p_aArgs) {
                        resetOptimalWeigths(myDataTable);

                        aDate = p_aArgs[0][0];
                        nMonth = aDate[1] - 1;
                        nDay = aDate[2];
                        nYear = aDate[0];
                        aDate = new Date(nYear, nMonth, nDay);

                        oReferenceDateButton.set("label", labelReferenceDateButton(aDate));
                        oReferenceDateButton.date = aDate;
                    }

                    oCalendarMenu.hide();
                });

                this.unsubscribe("click", onReferenceDateButtonClick);
            }

            oReferenceDateButton.on("click", onReferenceDateButtonClick);
        }

        function initTargetReturn() {
            var oTargetReturnMenu, oTargetReturnButton,
                oCurrentTargetReturn, oHTMLButton;

            oTargetReturnMenu = new YAHOO.widget.Menu("targetreturnmenu", {
                width: "120px", // 100 + 20
                zIndex: 4
            });

            oTargetReturnButton = new YAHOO.widget.Button({
                type: "menu",
                id: "targetreturnbutton",
                label: "<em id=\"targetreturnbutton-currenttargetreturn\"></em>",
                menu: oTargetReturnMenu,
                container: "targetReturn"
            });

            oTargetReturnButton.on("appendTo", function () {
                oTargetReturnMenu.setBody("<div id=\"slider-bg\" tabindex=\"1\" title=\"Slider\"><div id=\"slider-thumb\"><img width=\"17\" height=\"21\" src=\"images/thumb-n.gif\"></div></div>");
                oTargetReturnMenu.render(this.get("container"));
                oCurrentTargetReturn = Dom.get("targetreturnbutton-currenttargetreturn");
            });

            oHTMLButton = oTargetReturnButton.get("element")
                .getElementsByTagName("button")[0];
            oHTMLButton.id = "targetreturnbutton-button";

            oTargetReturnMenu.subscribe("render", function () {
                var oSlider, oSliderEl;

                oSlider = YAHOO.widget.Slider.getHorizSlider("slider-bg",
                    "slider-thumb", 0, 100, 1);
                if (nTargetReturn === undefined) {
                    nTargetReturn = 0;
                }
                oSlider.setValue(nTargetReturn / 0.01 / 0.15, true);

                oSliderEl = Dom.get("slider-bg");

                oSlider.subscribe("change", function () {
                    var nTargetReturnOld = nTargetReturn * 100 / 100,
                        nValue = Math.round(oSlider.getValue() * 0.15);


                    nTargetReturn = (nValue * 0.01);

                    oSliderEl.title = "Annual Target Return = " + nTargetReturn;
                    oCurrentTargetReturn.innerHTML = "Target Return " +
                        nValue + "%";

                    if (nTargetReturn !== nTargetReturnOld) {
                        resetOptimalWeigths(myDataTable);
                    }
                });
            });
        }

        function restoreBasket() {
            var basketRestored, data, i, lastBasket, referenceDate;

            lastBasket = YAHOO.util.Cookie.get(YAHOO.proplus.conpa.COOKIE);
            if (lastBasket !== null) {
                basketRestored = lastBasket.split(",");
                for (i = 0; i < basketRestored.length; i = i + 1) {
                    data = YAHOO.util.Cookie.getSubs(YAHOO.proplus.conpa.COOKIE +
                        "." + basketRestored[i]);
                    if (data !== null) {
                        data.symbol = basketRestored[i];
                        myDataTable.addRow(data);
                    }
                }
                referenceDate = new Date(YAHOO.util.Cookie.get(
                    YAHOO.proplus.conpa.COOKIE + ".referenceDate"));
                if (referenceDate !== null) {
                    oReferenceDateButton.set("label",
                        labelReferenceDateButton(referenceDate));
                    oReferenceDateButton.date = referenceDate;
                }
                nTargetReturn = YAHOO.util.Cookie.get(
                    YAHOO.proplus.conpa.COOKIE + ".targetReturn");
            }
        }

        initPanels();
        initAssetSearch();
        initBasketDataTable();
        initGetOptimalPortfolio();
        initReferenceDate();
        initTargetReturn();
        restoreBasket();
    };

    Y.on("domready", YAHOO.proplus.conpa.init);

});
