    /*

    Siesta 5.3.0
    Copyright(c) 2009-2019 Bryntum AB
    https://bryntum.com/contact
    https://bryntum.com/products/siesta/license

    */
    Ext.define('Siesta.Project.Browser.UI.CoverageReport', {
        extend : 'Ext.Container',
        alias  : 'widget.coveragereport',

        requires : [
            'Ext.tree.Panel',

            'Siesta.Project.Browser.UI.TreeFilterField',
            'Siesta.Project.Browser.UI.CoverageChart',

            'Siesta.Project.Browser.Model.FilterableTreeStore',
            'Siesta.Project.Browser.UI.FilterableTreeView',
            'Siesta.Project.Browser.Model.CoverageUnit',

            'Ext.layout.container.Border'
        ],

        cls    : 'st-cov-report-panel',
        layout : 'border',

        htmlReport       : null,
        treePanel        : null,
        treeStore        : null,
        chart            : null,
        sourcePanel      : null,
        contentContainer : null,
        toggleButtons    : null,
        standalone       : false,
        dataUrl          : null,
        project          : null,

        // Number of levels in the coverage class/file tree to expand by default
        expandLevels : 2,

        initComponent : function () {
            var me = this
            var standalone = this.standalone

            var store = this.treeStore = new Siesta.Project.Browser.Model.FilterableTreeStore({
                model       : 'Siesta.Project.Browser.Model.CoverageUnit',
                proxy       : 'memory',
                rootVisible : true
            })

            Ext.apply(this, {

                border : !this.standalone,
                items  : [
                    {
                        xtype              : 'treepanel',
                        border             : false,
                        region             : 'west',
                        enableColumnHide   : false,
                        enableColumnMove   : false,
                        enableColumnResize : false,
                        sortableColumns    : false,
                        rowLines           : false,
                        tbar               : {
                            cls    : 'siesta-toolbar',
                            height : 45,
                            border : false,
                            items  : [
                                standalone ? null : {
                                    text    : Siesta.Resource('Siesta.Project.Browser.UI.CoverageReport', 'closeText'),
                                    scale   : 'medium',
                                    style   : 'margin:0 10px 0 0;',
                                    handler : this.onBackToMainUI,
                                    scope   : this
                                },
                                {
                                    xtype           : 'treefilter',
                                    cls             : 'filterfield',
                                    hasAndCheck     : function () {
                                        var states = Ext.pluck(me.toggleButtons, 'pressed')

                                        return !states[0] || !states[1] || !states[2]
                                    },
                                    andChecker      : this.levelFilter,
                                    andCheckerScope : this,
                                    margin          : '3 0 0 0',
                                    store           : store,
                                    filterField     : 'text',
                                    width           : 180
                                },
                                '->',
                                {
                                    xtype  : 'label',
                                    text   : Siesta.Resource('Siesta.Project.Browser.UI.CoverageReport', 'showText'),
                                    margin : '0 5 0 0'
                                },
                                {
                                    text          : Siesta.Resource('Siesta.Project.Browser.UI.CoverageReport', 'highText'),
                                    level         : 'high',
                                    enableToggle  : true,
                                    pressed       : true,
                                    scale         : 'medium',
                                    cls           : 'st-cov-level-high',
                                    toggleHandler : this.toggleLevels,
                                    scope         : this,
                                    margin        : '0 5 0 0'
                                },
                                {
                                    text          : Siesta.Resource('Siesta.Project.Browser.UI.CoverageReport', 'mediumText'),
                                    level         : 'med',
                                    enableToggle  : true,
                                    scale         : 'medium',
                                    pressed       : true,
                                    cls           : 'st-cov-level-medium',
                                    toggleHandler : this.toggleLevels,
                                    scope         : this,
                                    margin        : '0 5 0 0'
                                },
                                {
                                    text          : Siesta.Resource('Siesta.Project.Browser.UI.CoverageReport', 'lowText'),
                                    level         : 'low',
                                    enableToggle  : true,
                                    scale         : 'medium',
                                    pressed       : true,
                                    cls           : 'st-cov-level-low',
                                    toggleHandler : this.toggleLevels,
                                    scope         : this,
                                    style         : 'margin:0 5px 0 0'
                                }
                            ]
                        },

                        viewType   : 'filterabletreeview',
                        viewConfig : {
                            store       : store.nodeStore,
                            trackOver   : false,
                            rootVisible : true
                        },

                        cls : 'st-cov-report-tree-panel',

                        flex        : 1,
                        split       : true,
                        rootVisible : true,

                        columns : [
                            {
                                xtype        : 'treecolumn',
                                dataIndex    : 'text',
                                menuDisabled : true,
                                flex         : 3
                            },
                            {
                                text         : Siesta.Resource('Siesta.Project.Browser.UI.CoverageReport', 'statementsText'),
                                flex         : 1,
                                menuDisabled : true,
                                tdCls        : 'cov-result-cell',
                                renderer     : this.getMetricsRenderer('statements')
                            },
                            {
                                text         : Siesta.Resource('Siesta.Project.Browser.UI.CoverageReport', 'branchesText'),
                                flex         : 1,
                                menuDisabled : true,
                                tdCls        : 'cov-result-cell',
                                renderer     : this.getMetricsRenderer('branches')
                            },
                            {
                                text         : Siesta.Resource('Siesta.Project.Browser.UI.CoverageReport', 'functionsText'),
                                flex         : 1,
                                menuDisabled : true,
                                tdCls        : 'cov-result-cell',
                                renderer     : this.getMetricsRenderer('functions')
                            },
                            {
                                text         : Siesta.Resource('Siesta.Project.Browser.UI.CoverageReport', 'linesText'),
                                flex         : 1,
                                menuDisabled : true,
                                tdCls        : 'cov-result-cell',
                                renderer     : this.getMetricsRenderer('lines')
                            }
                        ],

                        store : store,

                        listeners : {
                            selectionchange : this.onClassSelected,
                            scope     : this
                        }
                    },
                    {
                        xtype  : 'container',
                        cls    : 'coveragechart-container',
                        slot   : 'contentContainer',
                        region : 'center',
                        layout : {
                            type                : 'card',
                            deferredRendering   : true
                        },

                        items : [
                            {
                                xtype : 'coveragechart'
                            },
                            {
                                xtype       : 'panel',
                                slot        : 'sourcePanel',
                                flex        : 1,
                                autoScroll  : true,
                                bodyPadding : '4 0 4 10',
                                border      : false,
                                cls         : 'st-cov-report-source-panel'
                            }
                        ]

                    }
                ]
            })

            this.callParent()

            this.contentContainer = this.down('[slot=contentContainer]')
            this.chart            = this.down('chart')
            this.sourcePanel      = this.down('[slot=sourcePanel]')
            this.toggleButtons    = this.query('button[level]')
            this.treePanel        = this.down('treepanel')

            if (standalone) {
                // `loadingMask.show()` throws exception when called with non-rendered target
                this.on('afterrender', function () {
                    var loadingMask = new Ext.LoadMask({
                        target : this,
                        msg    : Siesta.Resource('Siesta.Project.Browser.UI.CoverageReport', 'loadingText')
                    });

                    loadingMask.show()

    //                use this code for testing
    //                setTimeout(function () {
    //                    loadingMask.hide()
    //
    //                    me.loadHtmlReport(me.htmlReport)
    //                }, 2000)

                    Ext.Ajax.request({
                        url : this.dataUrl,

                        success : function (response) {
                            loadingMask.hide()
                            me.loadHtmlReport(Ext.JSON.decode(response.responseText))
                        },

                        failure : function () {
                            loadingMask.hide()
                            Ext.Msg.show({
                                title   : Siesta.Resource('Siesta.Project.Browser.UI.CoverageReport', 'loadingErrorText'),
                                msg     : Siesta.Resource('Siesta.Project.Browser.UI.CoverageReport', 'loadingErrorMessageText') + me.dataUrl,
                                buttons : Ext.MessageBox.OK,
                                icon    : Ext.MessageBox.ERROR
                            })
                        }
                    })
                }, this, { single : true })
            } else if (this.htmlReport) {
                this.loadHtmlReport(this.htmlReport);
            }

            // Refresh data is user reruns a test with coverage panel open
            if (this.project) {
                this.project.on('testsuiteend', this.onTestSuiteEnd, this)
            }
        },

        onTestSuiteEnd : function (descriptors) {

            if (this.project && this.isVisible()) {
                // Load new data into coverage report
                this.loadHtmlReport(this.project.generateCoverageHtmlReport(false));
            }
        },

        loadHtmlReport : function (report) {
            this.htmlReport = report

            var treeStore = this.treeStore
            var isFile = report.coverageUnit == 'file'
            var treeFilter = this.down('treefilter')
            var selModel = this.treePanel.getSelectionModel();
            var selected = selModel.getSelected();
            var oldSelectedId = selected.length > 0 ? selected.first().getId() : null;

            treeStore.setRootNode(this.generateFilesTree(report.htmlReport.root))

            if (oldSelectedId && treeStore.getNodeById(oldSelectedId)){
                selModel.select(treeStore.getNodeById(oldSelectedId));
            }

            this.down('treecolumn').setText(isFile ? 'File name' : 'Class name')

            treeFilter.emptyText = isFile ? 'Filter files' : 'Filter classes'

            treeFilter.applyEmptyText();

            this.loadChartData(treeStore.getRootNode());
        },

        levelFilter : function (node) {
            var coverage = node.getStatementCoverage();

            if (coverage === undefined) return false;

            return this.toggleButtons[coverage >= 80 ? 0 : coverage >= 50 ? 1 : 2].pressed
        },

        toggleLevels : function () {
            this.down('treefilter').refreshFilter()
        },

        getCoverageLevelClass : function (coveragePct) {
            if (typeof coveragePct == 'number')
                return 'st-cov-level-' + (coveragePct >= 80 ? 'high' : coveragePct >= 50 ? 'medium' : 'low');
            else
                return ''
        },

        getMetricsRenderer : function (property) {
            var me = this

            return function (value, metaData, preloadFile) {
                var reportNode = preloadFile.get('reportNode')
                if (!reportNode) return ''

                var metrics = reportNode.metrics[property]

                metaData.tdCls = me.getCoverageLevelClass(metrics.pct)

                return '<span class="st-cov-stat-pct-' + property + '">' + Math.round(metrics.pct) + '%</span> ' +
                    '<span class="st-cov-stat-abs-' + property + '">(' + metrics.covered + '/' + metrics.total + ')</span>'
            }
        },

        generateFilesTree : function (node, depth) {
            var me = this
            depth = depth || 0;

            // in this method "node" should be treated as a raw JSON object and not an instance of Node from Istanbul
            // (even that in UI usage scenario it will be a Node)
            // since for the standalone report we load a JSON blob with the tree report
            // so we should not call any methods on "node"
            if (node.kind === 'dir') {
                var text = node.relativeName || node.fullName

                return {
                    id       : node.fullName,
                    url      : node.fullName,
                    leaf     : false,
                    expanded : depth < this.expandLevels,

                    text : text == '/' && this.htmlReport.coverageUnit == 'extjs_class' ? Siesta.Resource('Siesta.Project.Browser.UI.CoverageReport', 'globalNamespaceText') : text,

                    reportNode : node,

                    children : Ext.Array.map(node.children, function (childNode) {
                        return me.generateFilesTree(childNode, depth + 1)
                    }).sort(this.treeSorterFn)
                }
            } else {
                return {
                    id   : node.fullName,
                    url  : node.fullName,
                    leaf : true,

                    text : node.relativeName,

                    reportNode : node
                }
            }
        },

        treeSorterFn : function (node1, node2) {
            if (!node1.leaf && node2.leaf) return -1;

            if (node1.leaf && !node2.leaf) return 1;

            if (node1.leaf === node2.leaf) return node1.text < node2.text ? -1 : 1;
        },

        onClassSelected : function (view, records) {
            var record = records[0];

            if (!record) return;

            if (record.isLeaf() && !this.htmlReport.coverageNoSource) {
                this.sourcePanel.update(record.get('reportNode').html)
                prettyPrint()
                this.contentContainer.getLayout().setActiveItem(1)
            } else {
                this.loadChartData(record)
                this.contentContainer.getLayout().setActiveItem(0)
            }
        },

        onBackToMainUI : function () {
            this.fireEvent('backtomainui', this)
        },

        loadChartData : function (node) {
            this.chart.store.loadData([
                { name : 'Statements', value : Math.round(node.getStatementCoverage()) },
                { name : 'Branches', value : Math.round(node.getBranchCoverage()) },
                { name : 'Functions', value : Math.round(node.getFunctionCoverage()) },
                { name : 'Lines', value : Math.round(node.getLineCoverage()) }
            ])
        }
    });