// 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.view.main.ToolbarWithConfigurableComponents', {

    override: 'Shopware.apps.Analytics.view.main.Toolbar',

    initComponent: function () {
        this.callParent(arguments);
        this.viisonCommonAnalyticsComponentsToolbar = Object.create(null, {
            inViisonMode: { value: false, writable: true },
            activeComponents: { value: Object.create(null), writable: true },
        });
    },

    viisonCommonAnalyticsSetToolbarComponents: function (components, refreshedCallback) {
        if (!this.viisonCommonAnalyticsComponentsToolbar.inViisonMode) {
            this.viisonCommonAnalyticsComponentsToolbar.inViisonMode = true;
            this.viisonCommonAnalyticsComponentsToolbar.componentsBackup = Ext.clone(this.items.items);
        }

        Ext.each(Object.keys(this.viisonCommonAnalyticsComponentsToolbar.activeComponents), function (activeComponentId) {
            var activeComponent = this.viisonCommonAnalyticsComponentsToolbar.activeComponents[activeComponentId];
            if (!Object.prototype.hasOwnProperty.call(components, activeComponentId)) {
                // New components spec does not include activeComponentId. Remove.
                this.viisonCommonAnalyticsFindRenderedComponent(activeComponent).hide();
                delete this.viisonCommonAnalyticsComponentsToolbar.activeComponents[activeComponentId];

                return;
            }

            // TODO: Really update based on different specs.
            this.viisonCommonAnalyticsFindRenderedComponent(activeComponent).show();
            this.viisonCommonAnalyticsComponentsToolbar.activeComponents[activeComponentId] = components[activeComponentId];
        }, this);

        Ext.each(Object.keys(components), function (componentId) {
            var newComponent = components[componentId];
            if (!Object.prototype.hasOwnProperty.call(this.viisonCommonAnalyticsComponentsToolbar.activeComponents, componentId)) {
                // Does not exist in activeComponents. Is new.
                if (newComponent.componentConfig.isDefault) {
                    this.viisonCommonAnalyticsFindRenderedComponent(newComponent).show();

                    return;
                }

                // Add new filters after to_date
                // See Shopware.apps.Analytics.view.main.Toolbar for the default components and their order.
                var insertAfterName = 'to_date'; // magic constant
                this.viisonCommonAnalyticsAddToolbarItem(insertAfterName, [newComponent.componentConfig], refreshedCallback);
                this.viisonCommonAnalyticsComponentsToolbar.activeComponents[componentId] = Ext.clone(newComponent);
            }
        }, this);
    },

    viisonCommonAnalyticsFindRenderedComponent: function (component) {
        if (!component.componentConfig.name) {
            throw new Error('No name set on component definition.');
        }
        var widget = this.items.findBy(function (item) {
            return item.name === component.componentConfig.name;
        });
        if (widget === null) {
            throw new Error('Could not find component with name ' + component.componentConfig.name + '.');
        }

        return widget;
    },

    viisonCommonAnalyticsAddToolbarItem: function (insertAfterName, newItems, refreshedCallback) {
        /* Gather items from the Ext.util.AbstractMixedCollection in me.items. The collection has been initialized
         * in the parent's initComponents from an array of initial component configurations.
         * See Shopware.apps.Analytics.view.main.Toolbar. */
        var items = [];
        this.items.each(function (item) {
            /* items have already been converted to components by the parent's initComponents. Use their
             * initialConfig to be able to re-initialize them. */
            items.push(item);
        });
        // Find the existing toolbar item with the name export
        for (var i = 0; i < items.length; i += 1) {
            if (items[i].name === insertAfterName) {
                // Recreate items with newItems inserted after items[i].
                var beforeNewItems = items.slice(0, i + 1); // All items from beginning to items[i] (inclusive)
                var afterNewItems = items.slice(i + 1, items.length); // All items after items[i] (exclusive)
                items = Array.prototype.concat(
                    beforeNewItems,
                    newItems,
                    afterNewItems
                );
                this.viisonCommonAnalyticsSetAndRenderItems(items, refreshedCallback);

                return;
            }
        }
        // If we are here, we have not found the item with insertAfterName as a name. Insert at the end.
        items = items.concat(newItems);
        this.viisonCommonAnalyticsSetAndRenderItems(items, refreshedCallback);
    },

    viisonCommonAnalyticsSetAndRenderItems: function (items, refreshedCallback) {
        // Reset items
        Ext.apply(this, {
            items: items,
        });

        // As in (the inherited) Ext.container.AbstractContainer.initComponents, to recreate the components:
        this.getLayout();
        this.initItems();
        refreshedCallback();
    },

    viisonCommonAnalyticsRestoreToolbarComponents: function () {
        var backup = Ext.clone(this.viisonCommonAnalyticsComponentsToolbar.componentsBackup);

        // Hide all components which do not match the backed up components.
        this.items.each(function (item) {
            if (item.name === undefined) {
                // This is the case for spacers (xtype: tbspacer). We do not concern ourselves with them.
                return;
            }
            for (var b = 0; b < backup.length; b += 1) {
                if (backup[b].name === item.name) {
                    return; // We do not manipulate item. It's in the backup.
                }
            }
            item.hide();
        });
    },

});
