// 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.

//{namespace name="backend/viison_shipping_common_shipping/shipping"}
Ext.define('Shopware.apps.ViisonShippingCommonShipping.controller.Tab', {

    extend: 'Ext.app.Controller',

    /**
     * Contains all custom snippets for information and notifications.
     */
    snippets: {
        notifications: {
            createMappingSuccess: {
                title: '{s name="default_form/notifications/create_mapping_success/title"}{/s}',
                message: '{s name="default_form/notifications/create_mapping_success/message"}{/s}'
            },
            createMappingError: {
                title: '{s name="default_form/notifications/create_mapping_error/title"}{/s}',
                message: '{s name="default_form/notifications/create_mapping_error/message"}{/s}'
            },
            updateMappingSuccess: {
                title: '{s name="default_form/notifications/update_mapping_success/title"}{/s}',
                message: '{s name="default_form/notifications/update_mapping_success/message"}{/s}'
            },
            updateMappingError: {
                title: '{s name="default_form/notifications/update_mapping_error/title"}{/s}',
                message: '{s name="default_form/notifications/update_mapping_error/message"}{/s}'
            },
            destroyMappingSuccess: {
                title: '{s name="default_form/notifications/destroy_mapping_success/title"}{/s}',
                message: '{s name="default_form/notifications/destroy_mapping_success/message"}{/s}'
            },
            destroyMappingError: {
                title: '{s name="default_form/notifications/destroy_mapping_error/title"}{/s}',
                message: '{s name="default_form/notifications/destroy_mapping_error/message"}{/s}'
            },
            growlMessage: '{s name="default_form/notifications/growlMessage"}{/s}'
        }
    },

    /**
     * Add a reference to the dispatch service provider panel
     */
    constructor: function() {
        this.refs = (this.refs || []).concat([{
            ref: 'tab',
            selector: this.tabAlias
        }]);

        // Load custom stores
        this.productStore = this.getProductStore();
        this.productMappingStore = Ext.create(this.productMappingStoreClass);

        this.callParent(arguments);
    },

    /**
     * Create Product Store
     *
     * NOTE: So that every Adapter can override this method
     *       if the Store needs additional load logic, specific
     *       to the Adapter
     *
     * @returns Ext.Store
     */
    getProductStore: function() {
        return Ext.create(this.productStoreClass).load();
    },

    /**
     * Creates the necessary event listener for this specific controller and opens a new Ext.window.Window
     * to display the sub-application.
     */
    init: function() {
        var me = this;

        me.control({
            'button[action=saveDispatch]': {
                click: me.onDispatchSaveMapping
            }
        });

        me.getStore('Dispatch').on({
            load: { fn: me.onDispatchStoreLoaded, scope: me }
        });

        me.callParent(arguments);
    },

    /**
     * Determines whether the product mapping of this shipping method should be cloned,
     * created, updated or deleted and schedules the dedicated action.
     *
     * @param button The button firing the event.
     * @param event The event handled by this method.
     */
    onDispatchSaveMapping: function(button, event) {
        var me = this;

        // Get main record
        var record = button.up('window').down('form').getForm().getRecord();

        // Handle the different actions
        // TODO: Simplify if-blocks by minimalizing them to one block for both clone and new
        if (record.get('clone')) {
            // CLONED RECORD -> wait until main record was added to the database
            record.on('idchanged', function(record, oldId, newId, opts) {
                if (newId) {
                    // Perform the necessary CRUD operation
                    me.getTab().mappingForm.productMapping = undefined;
                    me.crudMapping(record);
                }
            });
        } else if (!record.get('clone') && record.phantom) {
            // NEW RECORD -> wait until the new record was created and added to the database
            me.oldRecordIds = [];
            var oldRecords = me.getStore('Dispatch').getRange();
            Ext.each(oldRecords, function(oldRecord) {
                me.oldRecordIds.push(oldRecord.data.id);
            });

            // Remove mapping from the form
            me.getTab().mappingForm.productMapping = undefined;
        } else {
            // UPDATE -> Perform the necessary CRUD operation
            me.crudMapping(record);
        }
    },

    /**
     * Performs the dedicated CRUD action for the product mapping based on the given data.
     *
     * @param record The record, whose mapping should be created, updated or deleted.
     */
    crudMapping: function(record) {
        var me = this;

        // Get new values and - if exists - the existing mapping
        var tab = me.getTab();

        var values = tab.mappingForm.getForm().getFieldValues();

        var gotNonEmptyValue = false;

        Ext.iterate(values, function(key, value) {
            if (value) {
                gotNonEmptyValue = true;
            }
        });

        var mapping = tab.mappingForm.productMapping;

        if (mapping === undefined && !gotNonEmptyValue) {
            return;
        } else if (mapping === undefined && gotNonEmptyValue) {
            // Create new mapping
            mapping = Ext.create(me.productMappingModelClass, Ext.apply({
                productId: values.product,
                dispatchId: record.data.id,
            }, values));
        } else { // mapping !== undefined
            // Update mapping with new product id
            mapping.set('productId', values.product);
            Ext.iterate(values, function(key, value) {
                if (key != 'product') {
                    mapping.set(key, value);
                }
            });
        }
        // Update or create the mapping
        mapping.save({
            callback: function(data, operation) {
                var notification = me.snippets.notifications.updateMappingSuccess;
                if (operation.success === true) {
                    if (operation.action === 'create') {
                        notification = me.snippets.notifications.createMappingSuccess;
                        // Add mapping to store
                        tab.productMappingStore.add(mapping);
                        tab.mappingForm.productMapping = mapping;
                    }
                } else {
                    notification = (operation.action === 'create') ? me.snippets.notifications.createMappingError : me.snippets.notifications.updateMappingError;
                }

                // Show notification
                Shopware.Notification.createGrowlMessage(me.fillSnippet(notification.title), me.fillSnippet(notification.message), me.snippets.notifications.growlMessage);
            }
        });
    },

    /**
     * Handles the 'load' events of the dispatch store. That is, if a new record was added,
     * the method to create a product mapping is triggered.
     *
     * @param store The store which triggered the event.
     * @param records An array containing all loaded records.
     * @param successful A boolean indicating whether the load operation was successful.
     * @param options Additional options of this event.
     */
    onDispatchStoreLoaded: function(store, records, successful, options) {
        var me = options.scope;
        if (!successful || me.oldRecordIds === undefined) {
            return;
        }

        // Check if a new record was added
        var record;
        Ext.each(records, function(curRecord) {
            if (me.oldRecordIds.indexOf(curRecord.data.id) == -1) {
                record = curRecord;
                return false; // break the Ext.each loop
            }
        });
        if (record === undefined) {
            // No records added
            return;
        }

        // Perform mapping creation
        me.crudMapping(record);

        // Remove temporary variables
        me.oldRecordIds = undefined;
    },

    /**
     * Delete the product mapping for the given dispatch type.
     *
     * @param record
     */
    onDispatchDeleteMapping: function(record) {
        var me = this;

        if (record !== undefined && record.data.id != 0) {
            // Find mapping
            var mappingIndex = me.productMappingStore.find('dispatchId', record.data.id);
            var mapping;
            if (mappingIndex > -1) {
                // Get mapping from store
                mapping = me.productMappingStore.getAt(mappingIndex);
            } else {
                // Create temporary mapping
                mapping = Ext.create(me.productMappingModelClass);
                mapping.set('dispatchId', record.data.id);
            }

            me.deleteMapping(mapping);
        }
    },

    /**
     * Load the product mapping when a new edit window is about to be opened.
     *
     * @param record The record for which a new edit form will be created.
     */
    createEditForm: function(record) {
        // Load mapping store
        this.productMappingStore.getProxy().extraParams = {
            dispatchId: record.internalId
        };
    },

    /**
     * Delete the given product mapping and show a notification reporting about the success of the operation.
     *
     * @param mapping
     */
    deleteMapping: function(mapping) {
        var me = this;
        // Delete mapping
        mapping.destroy({
            callback: function(data, operation) {
                var notification = me.snippets.notifications.destroyMappingError;
                if (operation.success) {
                    notification = me.snippets.notifications.destroyMappingSuccess;
                    // Remove the mapping from its store
                    me.productMappingStore.remove(mapping);
                    if (me.getTab()) { // if the window with the dispatch service provider tab is currently open
                        delete me.getTab().mappingForm.productMapping;
                    }
                }
                // Show notification
                Shopware.Notification.createGrowlMessage(me.fillSnippet(notification.title), me.fillSnippet(notification.message), me.snippets.notifications.growlMessage);
            }
        });
    },

    /**
     * Replaces occurrences of '[0]' with the name of the dispatch service provider (e.g. 'DHL').
     *
     * @param snippet string
     * @return string
     */
    fillSnippet: function(snippet) {
        return Ext.String.format(snippet, this.dispatchServiceProviderName);
    }
});
