/*

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

*/
Ext.define('Siesta.Project.Browser.UI.TestGrid', {
    extend     : 'Ext.tree.Panel',
    alias      : 'widget.testgrid',

    requires   : [
        'Siesta.Project.Browser.UI.FilterableTreeView',
        'Siesta.Project.Browser.UI.TestGridController',
        'Siesta.Project.Browser.UI.TestNameColumn'
    ],

    controller  : 'testgrid',

    stateful                : true,
    rootVisible             : false,
    header                  : false,
    rowLines                : false,
    useArrows               : true,
    border                  : false,
    cls                     : 'tr-testgrid',
    iconCls                 : 'tr-status-neutral-small',
    width                   : 340,
    collapsible             : true,
    expanded                : true,
    viewType                : 'filterabletreeview',
    enableColumnMove        : false,

    project                 : null,
    lines                   : false,

    filter                  : null,
    filterGroups            : false,

    resultSummary           : null,

    stateConfig             : null,

    showSizeControls        : false,

    isReadOnlyReport        : false,

    menuHideTimeout         : false,

    viewConfig : {
        enableTextSelection : true,
        toggleOnDblClick    : false,
        markDirty           : false,
        trackOver           : false,
        getRowClass         : function(record) {
            if (record.get('descriptor').isSystemDescriptor) {
                return 'siesta-system-descriptor';
            }
        },

        // Avoid DOM updates when irrelevant
        shouldUpdateCell    : function(record, column, changedFieldNames) {

            if (column.dataIndex === 'passCount' &&
                changedFieldNames &&
                !(
                    Ext.Array.contains(changedFieldNames, 'passCount') ||
                    Ext.Array.contains(changedFieldNames, 'todoPassCount')
                )
            ) {
                return 0;
            }

            if (column.dataIndex === 'failCount' &&
                changedFieldNames &&
                !(
                    Ext.Array.contains(changedFieldNames, 'failCount') ||
                    Ext.Array.contains(changedFieldNames, 'todoFailCount')
                )
            ) {
                return 0;
            }

            return Ext.tree.View.prototype.shouldUpdateCell.apply(this, arguments);
        }
    },

    initComponent : function () {
        var me      = this;
        var R       = Siesta.Resource('Siesta.Project.Browser.UI.TestGrid');
        var state   = this.stateConfig;

        Ext.apply(this, {
            title      : R.get('title'),

            columns : {
                // Hack, prevent Ext JS grid column to react to click/keys in filter field
                createFocusableContainerKeyNav  : Ext.emptyFn,
                // EOF Hack
                items                        : [
                    {
                        xtype   : 'testnamecolumn',
                        store   : this.store,
                        project : this.project
                    },
                    {
                        header       : R.get('passText'),
                        width        : 35,
                        sortable     : false,
                        tdCls        : 'x-unselectable result-cell',
                        menuDisabled : true,
                        dataIndex    : 'passCount',
                        align        : 'center',
                        renderer     : this.passedColumnRenderer,
                        scope        : this
                    },
                    {
                        header       : R.get('failText'),
                        width        : 35,
                        sortable     : false,
                        tdCls        : 'x-unselectable result-cell',
                        menuDisabled : true,
                        dataIndex    : 'failCount',
                        align        : 'center',
                        renderer     : this.failedColumnRenderer,
                        scope        : this
                    },
                    {
                        header      : 'Time',
                        width       : 50,
                        sortable    : false,
                        dataIndex   : 'time',
                        align       : 'center',
                        renderer    : function (value, meta, record) {
                            if (!record.isLeaf()) return ''
                            return value + 'ms';
                        },
                        hidden      : !(this.project.showTestDurationColumn || this.isReadOnlyReport)
                    }
                ]
            },

            bbar : {
                xtype    : 'toolbar',
                cls      : 'main-bbar siesta-toolbar',
                border   : false,
                height   : 45,
                defaults : {
                    scale       : 'large',
                    width       : 30,
                    tooltipType : 'title'
                },

                items : this.getBottomBarItems(state, R)
            },

            dockedItems : this.showSizeControls ? [
                {
                    xtype  : 'toolbar',
                    cls    : 'size-toolbar',
                    border : true,
                    dock   : 'bottom',
                    items  : [
                        {
                            xtype     : 'slider',
                            itemId    : 'framesizeSlider',
                            width     : 130,
                            value     : 3,
                            increment : 1,
                            minValue  : 0,
                            maxValue  : this.viewportSizes.length - 1,
                            listeners : {
                                change : this.onDimensionOrOrientationChange,
                                scope  : this
                            }
                        },
                        {
                            xtype  : 'label',
                            cls    : 'size-label',
                            itemId : 'sizeLabel',
                            width  : 65
                        },
                        {
                            boxLabel  : R.get('landscape'),
                            itemId    : 'orientationCheckbox',
                            xtype     : 'checkbox',
                            checked   : true,
                            listeners : {
                                change : this.onDimensionOrOrientationChange,
                                scope  : this
                            }
                        }
                    ]
                }
            ] : []
        })

        this.callParent(arguments);

        this.getView().on('beforerefresh', function () {
            var trigger = me.down('#trigger')

            if (me.filterGroups)    trigger.setFilterGroups(me.filterGroups)
            if (me.filter)          trigger.setValue(me.filter)

            // cancel refresh if there's a filter - in this case an additional refresh will be triggered by
            // the filtering which will be already not canceled since this is 1 time listener
            return !me.filter
        }, null, { single : true })

        this.on('viewready', this.onMyViewReady, this, { delay : 10 });
    },


    getBottomBarItems : function (state, R) {
        var items       = []

        if (!this.isReadOnlyReport) {
            items.push(
                {
                    glyph      : 0xf04b,
                    cls        : 'run-checked',
                    text       : '<span class="subicon fa-check"></span>',
                    tooltip    : R.get('runCheckedText'),
                    actionName : 'run-checked'
                },
                {
                    glyph      : 0xf04e,
                    cls        : 'run-all',
                    tooltip    : R.get('runAllText'),
                    actionName : 'run-all'
                },
                {
                    glyph      : 0xf04b,
                    cls        : 'run-failed',
                    text       : '<span class="subicon fa-bug"></span>',
                    tooltip    : R.get('runFailedText'),
                    actionName : 'run-failed'
                },
                {
                    glyph   : 0xf013,
                    tooltip : R.get('optionsText'),
                    cls     : 'options',
                    action  : 'options',

                    listeners : {
                        mouseover       : this.onOptionsButtonMouseOver,
                        mouseout        : this.onOptionsButtonMouseOut,
                        scope           : this
                    },

                    menu    : {
                        itemId : 'tool-menu',

                        listeners   : {
                            mouseenter  : {
                                fn      : this.onOptionsMenuMouseEnter,
                                // delay to cancel the hide _after_ the "mouseleave" from the sub-menu
                                delay   : 100
                            },
                            mouseover   : {
                                fn      : this.onOptionsMenuMouseEnter,
                                delay   : 100
                            },
                            mouseleave  : this.onOptionsMenuMouseLeave,
                            scope       : this
                        },

                        items  : [
                            {
                                text    : R.get('transparentExText'),
                                option  : 'transparentEx',
                                checked : state.transparentEx,

                                tooltip : R.get('transparentExTooltip')
                            },
//                            {
//                                text    : R.get('cachePreloadsText'),
//                                option  : 'cachePreload',
//                                checked : state.cachePreload
//                            },
                            {
                                text    : R.get('breakOnFailText'),
                                option  : 'breakOnFail',
                                checked : state.breakOnFail,

                                tooltip : R.get('breakOnFailTooltip')
                            },
                            {
                                text    : R.get('debuggerOnFailText'),
                                option  : 'debuggerOnFail',
                                checked : state.debuggerOnFail,

                                tooltip : R.get('debuggerOnFailTooltip')
                            },
                            {
                                itemId  : 'observerModeMenuItem',

                                text    : R.get('observerModeText'),
                                option  : 'observerMode',
                                checked : state.observerMode,

                                tooltip : R.get('observerModeTooltip')
                            },
                            {
                                text    : R.get('autoLaunchText'),
                                option  : 'autoRun',
                                checked : state.autoRun,

                                tooltip : R.get('autoLaunchTooltip')
                            },
                            { xtype : 'menuseparator' },
                            {
                                text   : R.get('aboutText'),
                                itemId : 'aboutSiesta'
                            },
                            {
                                text       : R.get('documentationText'),
                                href       : R.get('siestaDocsUrl'),
                                hrefTarget : '_blank'
                            }
                        ]
                    }
                }
            )
        }

        items.push(
            '->',
            {
                xtype  : 'component',
                cls    : 'summary-bar',
                border : false,
                width  : 55,
                itemId : 'result-summary',
                data   : {
                    pass : 0,
                    fail : 0
                },
                tpl    : '<div><span class="total-pass">{pass}</span><span class="icon fa-check"></span></div><div><span class="total-fail">{fail}</span><span class="icon fa-bug"></span></div>'
            }
        )

        return items
    },


    onHistoryChange : function(token) {
        if (token) {
            var testFile = this.store.getNodeById(token)

            if (testFile) {
                this.selectTestFile(testFile);
            }
        }
    },


    onDimensionOrOrientationChange : function (slider, val) {
        var newSize = this.viewportSizes[this.framesizeSlider.getValue()];
        var landscape = this.orientationCheckbox.getValue();

        this.sizeLabel.setText(newSize.join('x'));
        this.fireEvent('framesizechange', slider, newSize[0], newSize[1], landscape);
    },


    getFilterValue : function () {
        return this.down('#trigger').getValue()
    },


    getFilterGroups : function () {
        return this.down('#trigger').getFilterGroups()
    },


    passedColumnRenderer : function (value, meta, record) {
        if (!record.isLeaf()) return ''

        if (record.data.todoPassCount > 0) {
            value += ' <span title="' + record.data.todoPassCount + ' ' + Siesta.Resource('Siesta.Project.Browser.UI.TestGrid', 'todoPassedText') + '" class="tr-test-todo tr-test-todo-pass">+ ' + record.data.todoPassCount + '</span>';
        }

        return value;
    },


    failedColumnRenderer : function (value, meta, record) {
        if (!record.isLeaf()) return ''

        if (record.data.todoFailCount > 0) {
            value += ' <span title="' + record.data.todoFailCount + ' ' + Siesta.Resource('Siesta.Project.Browser.UI.TestGrid', 'todoFailedText') + '" class="tr-test-todo tr-test-todo-fail">+ ' + record.data.todoFailCount + '</span>';
        }
        return value;
    },


    onOptionsButtonMouseOver : function (button) {
        clearTimeout(this.menuHideTimeout)

        button.showMenu()

        button.menu.hide = function () {}
        setTimeout(function () {
            delete button.menu.hide
        }, 1000)
    },


    onOptionsButtonMouseOut : function (button) {
        var me      = this

        if (this.menuHideTimeout) return

        this.menuHideTimeout = setTimeout(function () {
            delete button.menu.hide
            button.hideMenu()

            me.menuHideTimeout  = null
        }, 500)
    },


    onOptionsMenuMouseEnter : function (menu) {
        clearTimeout(this.menuHideTimeout)

        this.menuHideTimeout    = null
    },


    onOptionsMenuMouseLeave : function () {
        var me          = this
        var menu        = this.down('#tool-menu')

        if (this.menuHideTimeout) return

        this.menuHideTimeout = setTimeout(function () {
            delete menu.hide
            menu.hide()

            me.menuHideTimeout  = null
        }, 500)
    },


    afterRender : function () {
        this.callParent(arguments);

        this.summaryPassEl  = this.el.down('.total-pass');
        this.summaryFailEl  = this.el.down('.total-fail');

        if (this.showSizeControls) {
            this.orientationCheckbox    = this.down('#orientationCheckbox');
            this.sizeLabel              = this.down('#sizeLabel');
            this.framesizeSlider        = this.down('#framesizeSlider');

            var size                    = this.viewportSizes[ this.framesizeSlider.getValue() ];

            this.sizeLabel.setText(size.join('x'));
        }
    },

    onMyViewReady : function() {
        Ext.History.on('change', this.onHistoryChange, this);

        var hash = window.location.hash;

        if (hash) {
            this.onHistoryChange(hash.substring(1));
        }
    },

    updateStatus : function (pass, fail) {
        this.summaryPassEl.update(String(pass));
        this.summaryFailEl.update(String(fail));
    },


    setFilterValue : function (value) {
        this.down('treefilter').setValue(value)
    },

    selectTestFile : function(testFile) {
        if (testFile) {
            testFile.bubble(function(parent) { parent.expand(); });

            // Make sure test is not filtered out
            if (this.store.getById(testFile.id) && this.store.indexOf(testFile) >= 0 ) {
                if (!this.getCollapsed() && this.getView().getNodes().length > 0) {
                    this.ensureVisible(testFile);
                }
                this.getSelectionModel().select(testFile)
            }
        }
    }
})