/*
    Class: DNow.ReportViewer
    This class creates a panel for use in viewing reports as managed by the <aw.ReportManager> class. A toolbar is built to provide functionality for setting the active report, active report type,
    saving, printing and exporting the active report.

    Inherits from:
    <aw.ui.Panel>
*/
DNow.ReportViewer = Class.create(aw.ui.Panel, {

    _activeReportFormat: null,

    _frame: null,

    _reportDropDown: null,

    _reportFormatGroup: null,
    _activeFormatButton: null,

    _url: null,

    _onActiveReportChanged_fx: null,
    _onReportsChanged_fx: null,
    _onActiveGeographyChanged_fx: null,
    _onActiveIndexBaseChanged_fx: null,

    /*
    Constructor: aw.ui.Panel.ReportViewer
    Creates a new instance of <aw.ui.Panel.ReportViewer>.

    Parameters:
    properties - {Object} A hash of property keys/values.
    events - {Object} A hash of events to register.
    */
    initialize: function (properties, events) {
        this._activeReportFormat = 'Comparison';
        this._frame = null;
        this._reportDropDown = null;
        this._reportFormatGroup = null;
        this._activeFormatButton = null;
        this._url = null;

        this.inheritCSS = true;

        aw.ui.Panel.prototype.initialize.apply(this, arguments);

        if (this.componentBus) {
            this.componentBus.getComponentReferences('aw.ReportManager', function (components) {
                if ((components) && (components.length > 0)) {
                    var rm = components[0];

                    this._onActiveReportChanged_fx = this._onActiveReportChanged.bind(this);
                    this._onReportsChanged_fx = this._onReportsChanged.bind(this);

                    rm.registerEvent('onactivereportchanged', this._onActiveReportChanged_fx);
                    rm.registerEvent('onreportschanged', this._onReportsChanged_fx);

                    var reports = rm.getAllReports();
                    if ((reports) && (reports.length > 0))
                        this._onReportsChanged(reports);

                    if (rm.activeReport)
                        this._onActiveReportChanged(rm.activeReport);
                }
            }.bind(this));

            this.componentBus.getComponentReferences('aw.GeographyManager', function (components) {
                if ((components) && (components.length > 0)) {
                    var gm = components[0];

                    this._onActiveGeographyChanged_fx = this._onActiveGeographyChanged.bind(this);
                    this._onActiveIndexBaseChanged_fx = this._onActiveIndexBaseChanged.bind(this);

                    gm.registerEvent('onactivegeographychanged', this._onActiveGeographyChanged_fx);
                    gm.registerEvent('onactiveindexbasechanged', this._onActiveIndexBaseChanged_fx);

                    if (gm.activeGeography)
                        this._onActiveGeographyChanged(gm.activeGeography);

                    if (gm.activeIndexBase)
                        this._onActiveIndexBaseChanged(gm.activeIndexBase);
                }
            }.bind(this));
        }
    },

    destroy: function () {
        var rm = this.componentBus.getComponentReferences('aw.ReportManager');
        if ((rm) && (rm.length > 0)) {
            rm = rm[0];
            if (this._onActiveReportChanged_fx)
                rm.unregisterEvent('onactivereportchanged', this._onActiveReportChanged_fx);

            if (this._onReportsChanged_fx)
                rm.unregisterEvent('onreportschanged', this._onReportsChanged_fx);
        }

        var gm = this.componentBus.getComponentReferences('aw.GeographyManager');
        if ((gm) && (gm.length > 0)) {
            gm = gm[0];
            if (this._onActiveGeographyChanged_fx)
                gm.unregisterEvent('onactivegeographychanged', this._onActiveGeographyChanged_fx);
        }

        aw.ui.Panel.prototype.destroy.apply(this);
    },

    draw: function () {
        aw.ui.Panel.prototype.draw.apply(this);

        this._reportDropDown = new aw.ui.Control.DropDown({
            'options': [{ 'value': '', 'label': 'Loading...'}]
        }, {
            'change': this._onReportDropDownChange.bind(this)
        });

        this._activeFormatButton = new aw.ui.Control.Button.Toggle({
            'label': 'Comparison',
            'toggled': true
        });

        this._reportFormatGroup = new aw.ui.Control.Button.Group({
            'items': [
                this._activeFormatButton,
                new aw.ui.Control.Button.Toggle({
                    'label': 'Summary'
                }),
                new aw.ui.Control.Button.Toggle({
                    'label': 'Rank'
                })//,
                //new aw.ui.Control.Button.Toggle({
                //    'label': 'List'
                //})
            ]
        }, {
            'toggle': this._onReportFormatToggle.bind(this)
        });

        //Rally US238 - Set Index Base, Rally US237 - Display Index Base
        _onIndexBaseSelected = function (geoCollection, minx, miny, maxx, maxy) {
            //Build the record store object with the new index
            var indexBase = {};
            var keys = [];
            var tree = null;

            indexBase.definition = geoCollection.getGeographyDefinition().geodef;
            var displayStr = "(" + geoCollection.geos.length + " selected) " + this.indexBaseDialog.getLongGeoName(geoCollection.geos[0].shortGeoName) + " : ";
            for (i = 0; i < geoCollection.geos.length; i++) {
                displayStr += geoCollection.geos[i].label + ", ";
                keys[i] = geoCollection.geos[i].shortGeoName + ":" + geoCollection.geos[i].geoKey;
            }
            displayStr = displayStr.substring(0, displayStr.length - 2);
            indexBase.display = displayStr;
            indexBase.keys = keys;

            //Update the geography manager's active index base in order to pass it to all reports
            var gm = this.componentBus.getComponentReferences('aw.GeographyManager');
            if ((gm) && (gm.length > 0))
                gm = gm[0];
            gm.activeIndexBase = geoCollection;

            //Re-run the active report with the new index base
            var rm = this.componentBus.getComponentReferences('aw.ReportManager');
            if ((rm) && (rm.length > 0))
                rm = rm[0];
            if (rm.activeReport)
                this._onActiveReportChanged(rm.activeReport);

            //Update the record store with the new index
            //var rs = new aw.RecordStore({
            //    'componentBus': this.componentBus
            //});
            this.setRecordStore([{ 'key': 'IndexBase', 'content': indexBase}]);

            //Display the new index
            var ibDiv = document.getElementById('indexBaseDiv');
            var disp = indexBase.display
            if (disp.length >= 100)
                disp = disp.substring(0, 100) + "...";
            ibDiv.innerHTML = disp;
        };

        _createIndexBaseDialog = function () {
            if (!this.indexBaseDialog)
                this.indexBaseDialog = new DNow.IndexBaseDialog({ 'componentBus': this.componentBus, 'closeable': false }, { 'ongeographyselected': _onIndexBaseSelected.bind(this) });
            else this.indexBaseDialog.show();
        };

        this.indexBaseGroup = new aw.ui.Toolbar.Group({
            'label': 'Index Base',
            'cssClass': 'indexToolbarGroup',
            'componentBus': this.componentBus,
            'items': [
                new aw.ui.HTML({
                    html: "<div id='indexBaseDiv'>Loading...</div>"
                }),
                new aw.ui.Control.Button({
                    'label': 'Change',
                    'cssClass': 'indexChangeButton'
                }, {
                    'click': _createIndexBaseDialog.bind(this)
                })
            ]
        });
        //------------------------

        this.add(
            new aw.ui.Toolbar({
                'region': 'top',
                'height': 100,
                'cssClass': 'DNow_Toolbar',
                'items': [
                    new aw.ui.Toolbar.Group({
                        'label': 'Geography Selection',
                        'cssClass': 'geoselection',
                        'items': [
                            new DNow.GeographyBar({
                                'componentBus': this.componentBus
                            })
                        ],
                        'helpCallback': this._onHelpClick.bind(this, 'Geography Selection')
                    }),
                    new aw.ui.Toolbar.Group({
                        'label': 'Report Type',
                        'items': [
                            new aw.ui.Toolbar.Column({
                                'items': [
                                    new aw.ui.Toolbar.Row({
                                        'items': [
                                            this._reportFormatGroup
                                        ]
                                    }),
                                    new aw.ui.Toolbar.Row({
                                        'items': [
                                            this._reportDropDown
                                        ]
                                    })
                                ]
                            })
                        ],
                        'helpCallback': this._onHelpClick.bind(this, 'Report:Report Types')
                    }),
                    new aw.ui.Toolbar.Group({
                        'label': 'File Options',
                        'items': [
                            new aw.ui.Toolbar.Column({
                                'items': [
                                    new aw.ui.Toolbar.Row({
                                        'items': [
                                            new aw.ui.Control.Button({
                                                'label': 'View Saved Reports'
                                            }, {
                                                'click': this._onViewSavedReportsClick.bind(this)
                                            }),
                                            new aw.ui.Control.Button({
                                                'label': 'Save'
                                            }, {
                                                'click': this._onSaveReportClick.bind(this)
                                            }),
                                            new aw.ui.Control.Button({
                                                'label': 'Print',
                                                'icon': './core/img/Misc/printer.png'
                                            }, {
                                                'click': this._onPrintReportClick.bind(this)
                                            })
                                        ]
                                    }),
                                    new aw.ui.Toolbar.Row({
                                        'items': [
                                            new aw.ui.Control.Button.Split({
                                                'items': [
                                                    new aw.ui.Control.Button({
                                                        'label': 'Export As PDF',
                                                        'icon': './core/img/Misc/acrobat.png'
                                                    }, {
                                                        'click': this._onExportReportClick.bind(this, 'pdf')
                                                    }), new aw.ui.Control.Button({
                                                        'label': 'Export As XLSX',
                                                        'icon': './core/img/Misc/excel.png'
                                                    }, {
                                                        'click': this._onExportReportClick.bind(this, 'xlsx')
                                                    }), new aw.ui.Control.Button({
                                                        'label': 'Export As DOCX',
                                                        'icon': './core/img/Misc/word.png'
                                                    }, {
                                                        'click': this._onExportReportClick.bind(this, 'docx')
                                                    })
                                                ]
                                            })
                                        ]
                                    })
                                ]
                            })
                        ],
                        'helpCallback': this._onHelpClick.bind(this, 'Report:File Options')
                    }),
                    this.indexBaseGroup
                ]
            }));

        var contents = this.canvas.down('div.contents');
        if (contents) {
            var frameId = this.getId('awf');
            contents.insert('<iframe id="' + frameId + '" name="' + frameId + '"></iframe>');

            this._frame = this.canvas.down('iframe');
        }

        return this.canvas;
    },

    /*
    Method: executeReport
    Dispatches a request to the server to generate the specified report with the specified <aw.GeographyCollection>.

    Parameters:
    geoCollection - {<aw.GeographyCollection>} A valid GeographyCollection.
    indexBase - {<aw.GeographyCollection>} (Optional) The index base selection.
    report - {Object} A reference to the report to execute.

    Returns:
    None.
    */
    executeReport: function (geoCollection, indexBase, report) {
        if ((!geoCollection) || (!report))
            return;

        if ((report.format.toLowerCase() == 'comparison') && (geoCollection) && (geoCollection.getGeographyCount() > 16)) {
            new aw.ui.Dialog.Alert({ 'title': 'Too Many Geographies!', 'content': 'No more than 16 geographies may be selected for a comparison report.' });

            var rm = this.componentBus.getComponentReferences('aw.ReportManager');
            if ((rm) && (rm.length > 0)) {
                var r = rm[0].getReportsByFormat('summary');
                if ((r) && (r.length > 0))
                    rm[0].setActiveReport(r[0]);
            }
            return;
        }

        var url = [];
        url.push('cn=SRC.Web.Client.Handler.ReportHandler');
        url.push('service=loading');
        if (this.componentBus.getApplicationKey())
            url.push('akey=' + this.componentBus.getApplicationKey());

        if (this._frame)
            this._frame.src = this.componentBus.getComponentServer() + '?' + url.join('&');

        if (report.type == 'Calgary') {
            var req = { 'cn': 'SRC.Web.Client.Handler.CalgaryHandler' + ((report.variant) ? ('|' + report.variant) : ''), 'service': 'buildCalgaryQuery', 'query': report.query };
            Object.extend(req, geoCollection.getGeographyDefinition());

            this.request(req, function (geoCollection, report, classname, o) {
                if ((!o) || (!o.payload) || (!o.payload.query))
                    return;

                var _report = Object.clone(report);
                _report.query = o.payload.query;

                this._executeReport(geoCollection, indexBase, _report);
            }.bind(this, geoCollection, report));

            return;
        }

        this._executeReport(geoCollection, indexBase, report);
    },

    /*
    Method: renderReport
    */
    renderReport: function (o, format) {
        this._url = this._getReportExportURL(o, format);

        if (this._frame)
            this._frame.src = this._url;
    },

    /*
    Method: setActiveReportFormat
    */
    setActiveReportFormat: function (format) {
        if ((!format) || (!format.match('Comparison|Summary|Rank|List')))
            return false;

        var rm = this.componentBus.getComponentReferences('aw.ReportManager');
        if ((rm) && (rm.length > 0)) {
            rm = rm[0];

            var reports = rm.getReportsBy({ 'format': format, 'listOnly': false });
            if ((!reports) || (!reports.length > 0)) {
                new aw.ui.Dialog.Error({ 'title': 'No Reports Available', 'content': 'You do not have any ' + format + ' reports available.<br />Please contact our sales team.' });
                return false;
            }

            if (format == this._activeReportFormat)
                return true;

            this._activeReportFormat = format;
            this._onReportsChanged(rm.getAllReports());

            if (this._reportDropDown)
                this._onReportDropDownChange(this._reportDropDown);

            return true;
        }

        return false;
    },

    _executeReport: function (geoCollection, indexBase, report) {
        var req = {
            'cn': 'SRC.Web.Client.Handler.' + ((report.type == 'Alteryx' || report.type == 'Calgary') ? 'AlteryxHandler' : 'AllocateHandler') + ((report.variant && report.variant !== '' && report.type != 'Calgary') ? ('|' + report.variant) : ''),
            'service': 'executeReport',
            'type': report.type,
            'format': report.format
        };

        if (report.type == 'Calgary') {
            Object.extend(req, {
                'dataset': report.variant,
                'query': report.query,
                'queryName': report.name
            });
        } else {
            Object.extend(req, {
                'report': report.name
            });
        }

        if ((report.format) && ((report.format.toLowerCase() == 'summary') || (report.format.toLowerCase() == 'list')))
            geoCollection.summarizeRadii(true);
        else
            geoCollection.summarizeRadii(false);

        Object.extend(req, geoCollection.getGeographyDefinition());
        if (indexBase) {
            var indexBaseDef = indexBase.getGeographyDefinition();
            if ((indexBaseDef) && (indexBaseDef.geodef))
                req.indexbase = indexBaseDef.geodef;
        }

        this.request(req, function (classname, o) {
            if ((!o) || (!o.payload))
                return;

            this.renderReport(o.payload, 'html');
        }.bind(this));
    },

    _getReportExportURL: function (o, format) {
        format = ((format) && (format.toLowerCase().match('pdf|xlsx|docx|html'))) ? format.toLowerCase() : 'html';

        var url = [];
        url.push('cn=SRC.Web.Client.Handler.ReportHandler');
        url.push('service=render');
        url.push('report=' + escape(o.report));
        url.push('type=' + escape(o.type));
        url.push('format=' + escape(format));
        url.push('seqId=' + this.getId(''));

        if (this.componentBus.getApplicationKey())
            url.push('akey=' + this.componentBus.getApplicationKey());

        if (this.componentBus.getSessionKey())
            url.push('skey=' + this.componentBus.getSessionKey());

        return this.componentBus.getComponentServer() + '?' + url.join('&');
    },

    _onActiveGeographyChanged: function (geoCollection) {
        var rm = this.componentBus.getComponentReferences('aw.ReportManager');
        if ((rm) && (rm.length > 0)) {
            rm = rm[0];

            if (rm.activeReport) {
                var gm = this.componentBus.getComponentReferences('aw.GeographyManager');
                if ((gm) && (gm.length > 0))
                    gm = gm[0];

                this.executeReport(geoCollection, gm.activeIndexBase, rm.activeReport);
            }
        }
    },

    _onActiveIndexBaseChanged: function (geoCollection) {
        var rm = this.componentBus.getComponentReferences('aw.ReportManager');
        if ((rm) && (rm.length > 0)) {
            rm = rm[0];

            if (rm.activeReport) {
                var gm = this.componentBus.getComponentReferences('aw.GeographyManager');
                if ((gm) && (gm.length > 0))
                    gm = gm[0];

                this.executeReport(gm.activeGeography, geoCollection, rm.activeReport);
            }
        }
    },

    _onActiveReportChanged: function (report) {
        if ((this._activeReportFormat != report.format) && (this._reportFormatGroup)) {
            var formatButton = this._reportFormatGroup.getItemBy({ 'label': report.format });
            if (formatButton) {
                formatButton.setToggled(true);
                return;
            }
        }

        this._activeReportFormat = report.format;
        var rm = this.componentBus.getComponentReferences('aw.ReportManager');
        if ((rm) && (rm.length > 0)) {
            rm = rm[0];
            this._onReportsChanged(rm.getAllReports());
        }

        if (this._reportDropDown)
            this._reportDropDown.selectByValue(report.key, false);

        var gm = this.componentBus.getComponentReferences('aw.GeographyManager');
        if ((gm) && (gm.length > 0)) {
            gm = gm[0];

            if (gm.activeGeography)
                this.executeReport(gm.activeGeography, gm.activeIndexBase, report);
        }
    },

    _onExportReportClick: function (format, control) {
        if (this.isSessionValidated() !== true) {
            new aw.ui.Dialog.Error({ 'title': 'Access Denied', 'content': 'You must be logged in to access this functionality.' });
            return;
        }

        if (!this._frame)
            return;

        var url = this._url.replace(/\&format=\w+/gi, '').replace(/\&seqId=\w+/gi, '');
        url += '&seqId=' + this.getId('');
        url += '&format=' + format;

        this._frame.src = url;
    },

    _onHelpClick: function (topic) {
        if (this.componentBus) {
            var help = this.componentBus.getComponentReferences('DNow.Help');
            if ((help) && (help.length > 0)) {
                help[0].loadTopicByTitle(topic);
                return;
            }
        }

        new DNow.Help({
            'componentBus': this.componentBus,
            'activeTopicKey': topic
        });
    },

    _onPrintReportClick: function (control) {
        if (this.isSessionValidated() === true) {
            if (this._frame) {
                if ((document) && (document[this._frame.readAttribute('id')])) {
                    document[this._frame.readAttribute('id')].focus();
                    document[this._frame.readAttribute('id')].print();
                } else if ((window) && (window.frames) && (window.frames[this._frame.readAttribute('id')])) {
                    window.frames[this._frame.readAttribute('id')].focus();
                    window.frames[this._frame.readAttribute('id')].print();
                } else {
                    new aw.ui.Dialog.Error({ 'title': 'Print Error!', 'content': 'Your browser does not appear to support report printing capabilities.' });
                }
            }
        } else {
            new aw.ui.Dialog.Error({ 'title': 'Access Denied', 'content': 'You must be logged in to access this functionality.' });
        }
    },

    _onReportDropDownChange: function (control) {
        var rm = this.componentBus.getComponentReferences('aw.ReportManager');
        if ((rm) && (rm.length > 0)) {
            rm = rm[0];
            rm.setActiveReportByKey(control.getValue());
        }
    },

    _onReportFormatToggle: function (control, activeControl) {
        if (this._activeFormatButton === activeControl)
            return;

        if (this.setActiveReportFormat(activeControl.label) !== true) {
            this._activeFormatButton.setToggled(true);
            return;
        }

        this._activeFormatButton = activeControl;
    },

    _onReportsChanged: function (reports) {
        if ((!reports) || (!this._reportDropDown))
            return;

        this._reportDropDown.clear();

        var rm = this.componentBus.getComponentReferences('aw.ReportManager');
        if ((!rm) || (!rm.length > 0))
            return;

        rm = rm[0];

        var report = null;
        for (var i = 0; report = reports[i]; i++) {
            if (report.format == this._activeReportFormat)
                this._reportDropDown.addOption(report.key, report.label, report.listOnly, ((report === rm.activeReport) ? true : false));
        }
    },

    _onSaveReportClick: function (control) {
        if (this.isSessionValidated() === true) {
            var rm = this.componentBus.getComponentReferences('aw.ReportManager');
            if ((rm) && (rm.length > 0))
                rm[0].saveActiveReport();
        } else {
            new aw.ui.Dialog.Error({ 'title': 'Access Denied', 'content': 'You must be logged in to access this functionality.' });
        }
    },

    _onViewSavedReportsClick: function (control) {
        if (this.isSessionValidated() === true) {
            var udm = this.componentBus.getComponentReferences('aw.UserDataManager');
            if ((udm) && (udm.length > 0)) {
                var fv = this.componentBus.getComponentReferences('DNow.FileViewer');
                if ((fv) && (fv.length > 0)) {
                    fv[0].setActiveDataType(udm[0].getDataTypeByLabel('Saved Reports'));
                    fv[0].show();
                }
            }
        } else {
            new aw.ui.Dialog.Error({ 'title': 'Access Denied', 'content': 'You must be logged in to access this functionality.' });
        }
    },

    CLASS_NAME: 'DNow.ReportViewer'
});
