// Copyright (c) Pickware GmbH. All rights reserved.
// This file is part of software that is released under a proprietary license.
// You must not copy, modify, distribute, make publicly available, or execute
// its contents or parts thereof without express permission by the copyright
// holder, unless otherwise permitted by law.

Ext.define('Shopware.apps.ViisonCommonAnalytics.controller.Main', {

    override: 'Shopware.apps.Analytics.controller.Main',

    /**
     * The default timeout for all Shopware requests.
     */
    defaultBackendAjaxTimeout: null,

    constructor: function () {
        this.viisonCommonAnalytics = {
            analyses: Object.create(null),
            selectedAnalysisId: null,
        };

        this.defaultBackendAjaxTimeout = Ext.Ajax.timeout;

        return this.callParent(arguments);
    },

    addViisonCommonAnalysis: function (id, analysis) {
        // Do not allow to override basic object properties.
        if (Object.prototype.hasOwnProperty(id)) { // eslint-disable-line no-prototype-builtins
            throw new Error('Invalid name for VIISON analysis id: ' + id);
        }

        this.viisonCommonAnalytics.analyses[id] = analysis;
    },

    viisonCommonAnalyticsGetAnalysisParams: function (analysis) {
        var paramMap = Object.create(null);
        analysis.moduleHandler.onBuildRequestParamMap(this, analysis, paramMap);

        return paramMap;
    },

    viisonCommonAnalyticsOnExport: function (analysis) {
        var params = this.viisonCommonAnalyticsGetAnalysisParams(analysis);

        /* The URL construction is analogous to Shopware.apps.Analytics.controller.Main#onExport, except we add the
         * parameters dynamically. */
        var url = this.currentStore.getProxy().url;

        if (url.indexOf('?') === -1) {
            url += '?';
        } else {
            url += '&';
        }

        url += 'format=csv&'; // To trigger the download.

        var urlParams = [];
        Ext.each(Object.keys(params), function (paramName) {
            var paramValue = params[paramName];
            if (paramValue === undefined || paramValue === '') {
                return;
            }

            urlParams.push(encodeURIComponent(paramName) + '=' + encodeURIComponent(paramValue));
        });
        url += urlParams.join('&');

        // Submit the same way as Shopware.apps.Analytics.controller.Main#onExport:
        var form = Ext.create('Ext.form.Panel', {
            standardSubmit: true,
            target: 'iframe',
        });

        form.submit({
            method: 'POST',
            url: url,
        });
    },

    viisonCommonAnalyticsGetToolbar: function () {
        var toolbarRef = {
            ref: 'ViisonCommonAnalysisToolbar',
            selector: 'analytics-toolbar',
        };

        var backupRefs = this.refs;

        try {
            var newRefs = Ext.clone(this.refs);
            newRefs = newRefs || [];
            newRefs = newRefs.concat(toolbarRef);
            this.refs = newRefs;
            this.ref(this.refs);

            return this.getViisonCommonAnalysisToolbar();
        } finally {
            // Restore refs:
            if (this.refs !== backupRefs) {
                this.refs = backupRefs;
                this.ref(this.refs);
            }
        }
    },

    viisonCommonAnalyticsOnToolbarRefreshed: function () {
        this.ref(this.refs);
    },

    viisonCommonAnalyticsRenderDataOutput: function (store, record, analysis) {
        /* Copied from Shopware.apps.Analytics.controller.Main#renderDataOutput.
         * Copied from commit 33a4a2d3c4caac15205763785c3a26e5b7a0cd69, dated Tue Jan 27 17:52:48 2015 +0100.
         * Current, as of Shopware v5.1.1.
         * COPY_BEGIN */
        var chartId = 'widget.analytics-chart-' + record.data.id;
        var tableId = 'widget.analytics-table-' + record.data.id;
        var panel = this.getPanel();
        var layout = true;
        // var fromValue = this.getFromField().value;
        // var toValue = this.getToField().value;

        // Remove all previous inserted charts / tables
        Ext.suspendLayouts();
        panel.removeAll(true);
        panel.setLoading(true);

        Ext.apply(store.getProxy().extraParams, {
            node: 'root',
        });

        /* COPY_INTERRUPT - custom code */
        // Extend with analysis parameters from analysis module
        var params = this.viisonCommonAnalyticsGetAnalysisParams(analysis);
        Ext.each(Object.keys(params), function (paramName) {
            var paramValue = params[paramName];
            if (paramValue === undefined || paramValue === '') {
                delete store.getProxy().extraParams[paramName];
            }
            store.getProxy().extraParams[paramName] = paramValue;
        });
        /* COPY_INTERRUPT_END */

        /* // COPY_REMOVED - we do our own parameter handling above.
        if (Ext.typeOf(fromValue) == 'date') {
            store.getProxy().extraParams.fromDate = fromValue;
        }
        if (Ext.typeOf(toValue) == 'date') {
            store.getProxy().extraParams.toDate = toValue;
        }
        if (this.getShopSelection() && this.getShopSelection().getValue()) {
            store.getProxy().extraParams.selectedShops = this.getShopSelection().getValue().toString();
        }
        // COPY_REMOVED_END */

        this.currentStore = store;
        this.currentNavigationItem = record;

        if (this.getNavigation()) {
            this.getNavigation().setLoading(true);
        }

        store.load({
            scope: this,
            callback: function (result, request) {
                if (this.getNavigation()) {
                    this.getNavigation().setLoading(false);
                }
                panel.setLoading(false);

                if (request.success === false) {
                    return;
                }

                if (Ext.ClassManager.getNameByAlias(chartId)) {
                    var chart = Ext.create(chartId, {
                        store: store,
                        shopStore: this.shopStore,
                        shopSelection: this.getShopSelection().value,
                    });

                    panel.add(chart);
                } else {
                    layout = false;
                }

                if (Ext.ClassManager.getNameByAlias(tableId)) {
                    var table = Ext.create(tableId, {
                        store: store,
                        shopStore: this.shopStore,
                        shopSelection: this.getShopSelection().value,
                    });
                    panel.add(table);
                } else {
                    layout = false;
                }

                if (record.raw.multiShop) {
                    this.getShopSelection().show();
                } else {
                    this.getShopSelection().hide();
                }

                /* COPY_INTERRUPT - custom code, not from Shopware. */
                /* Workaround for ViisonArticleAnalytics.
                 * ViisonArticleAnalytics overrides this method, as well. Since we only follow the normal
                 * inheritance call chain when NOT moving to a VIISON Common Analysis, we will never call
                 * ViisonArticleAnalytics' logic for hiding its toolbar widgets when transitioning to a Viison Common
                 * Analysis. This workaround is at least necessary as of 2016-01-16, ViisonArticleAnalytics v1.0.10. */
                if (!(record.data.id === 'article'
                        && record.data.action === 'order_viison_article_analytics_article')) {
                    if (this.getCategorySelection !== undefined) {
                        this.getCategorySelection().hide();
                    }
                    if (this.getCustomerGroupsSelection !== undefined) {
                        this.getCustomerGroupsSelection().hide();
                    }
                }
                /* COPY_INTERRUPT_END */

                var activeItem;
                if (!layout) {
                    this.getLayoutButton().hide();
                    activeItem = 0;
                } else {
                    this.getLayoutButton().show();
                    activeItem = this.getLayoutButton().getActiveItem();

                    activeItem = (activeItem.layout === 'table') ? 0 : 1;
                }

                panel.getLayout().setActiveItem(activeItem);

                Ext.resumeLayouts(true);
            },
        });
        /* COPY_END */
    },

    /**
     * Adjust the Ajax timeout within the backend so that we can have request which take longer than 30 seconds.
     *
     * @param {int} timeoutInMilliseconds
     */
    setBackendAjaxTimeout: function (timeoutInMilliseconds) {
        Ext.Ajax.timeout = timeoutInMilliseconds;
        Ext.override(Ext.data.proxy.Server, { timeout: Ext.Ajax.timeout });
        Ext.override(Ext.data.Connection, { timeout: Ext.Ajax.timeout });
    },

    onExport: function () {
        // If the current analysis is a ViisonCommonAnalytics compatible analysis:
        if (this.viisonCommonAnalytics.selectedAnalysisId !== null) {
            return this.viisonCommonAnalyticsOnExport(
                this.viisonCommonAnalytics.analyses[this.viisonCommonAnalytics.selectedAnalysisId]
            );
        }

        return this.callParent(arguments);
    },

    renderDataOutput: function (store, record) {
        var nextAnalysis = null;

        var previousAnalysisId = this.viisonCommonAnalytics.selectedAnalysisId;
        var previousAnalysis = null;
        if (previousAnalysisId !== null) {
            previousAnalysis = this.viisonCommonAnalytics.analyses[previousAnalysisId];
        }

        this.viisonCommonAnalytics.selectedAnalysisId = null;

        // If the current analysis is a ViisonCommonAnalytics compatible analysis:
        if (record.raw.viisonCommonAnalysisId !== undefined) {
            var nextAnalysisId = record.raw.viisonCommonAnalysisId;
            nextAnalysis = this.viisonCommonAnalytics.analyses[nextAnalysisId];

            if (previousAnalysis !== null) {
                previousAnalysis.moduleHandler.onLeaveAnalysis(this, store, record, previousAnalysis, nextAnalysis);
            }

            nextAnalysis.moduleHandler.onBeforeRenderDataOutput(this, store, record, previousAnalysis, nextAnalysis);

            this.viisonCommonAnalytics.selectedAnalysisId = nextAnalysisId; // Clear remembered analysis id.

            // Adjust the shopware backend timeout in order to be able to have an analysis run for more then 30 seconds.
            store.removeListener('beforeload', this.onBeforeStoreLoadListener, this);
            store.addListener('beforeload', this.onBeforeStoreLoadListener, this);
            store.removeListener('load', this.onStoreLoadListener, this);
            store.addListener('load', this.onStoreLoadListener, this);

            return this.viisonCommonAnalyticsRenderDataOutput(store, record, nextAnalysis);
        }

        if (previousAnalysis !== null) {
            previousAnalysis.moduleHandler.onLeaveAnalysis(this, store, record, previousAnalysis, null);
        }

        this.viisonCommonAnalytics.selectedAnalysisId = null; // Clear remembered analysis id.

        return this.callParent(arguments);
    },

    /**
     * This listener will be called before the analytic's store is loaded in order to be able to adjust the
     * default backend ajax timeout. As a result we can run analytics that take more than 30 seconds.
     */
    onBeforeStoreLoadListener: function () {
        var millisecondsPerMinute = 60000;
        this.setBackendAjaxTimeout(Math.max(5 * millisecondsPerMinute, this.defaultBackendAjaxTimeout));
    },

    /**
     * This listener will be called after the analytic's store has been loaded to reset the default backend ajax time.
     */
    onStoreLoadListener: function () {
        this.setBackendAjaxTimeout(this.defaultBackendAjaxTimeout);
    },

});
