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

/**
 * This abstract controller implements the application logic of a dispatch service
 * provider tab that is part of the order detail window.
 */
//{namespace name="backend/viison_shipping_common_order/order"}
Ext.define('Shopware.apps.ViisonShippingCommonOrder.controller.Tab', {

    /**
     * Extend from the ShippingLabels controller.
     */
    extend: 'Shopware.apps.ViisonShippingCommonOrder.controller.ShippingLabels',

    /**
     * Class name for Order Config Store
     */
    orderConfigDataClass: 'Shopware.apps.ViisonShippingCommonOrder.store.OrderConfigData',

    /**
     * Override if adapter supports batch label creation of given order.
     * Example: '{url controller="ViisonShippingCommonOrder" action="getMergedLabelsForOrder"}'
     */
    mergedLabelsFromOrderActionUrl: null,

    /**
     * Adds additional event listeners.
     */
    init: function () {
        var eventMappings = {
            'order-detail-window': {
                afterrender: this.onAfterRender,
            },
        };

        this.labelPanelSelector = 'order-detail-window ' + this.dispatchServiceProviderPanelClass;
        eventMappings[this.labelPanelSelector] = {
            getAllLabelsFromOrderAsPdf: this.onGetAllLabelsFromOrderAsPDF,
        };
        this.control(eventMappings);

        this.addCreationPanelConstraints();

        this.callParent(arguments);
    },

    /**
     * Event handler to manage button click for merged labels inside a order.
     *
     * @param int orderId
     * @param store shippingStore
     * @param string errorTitle
     * @param string errorMessage
     */
    onGetAllLabelsFromOrderAsPDF: function (orderId, shippingStore, errorTitle, errorMessage) {
        var sendRequest = (shippingStore.count() !== 0 && shippingStore.findRecord('returnShipment', false));
        if (!sendRequest) {
            Ext.Msg.alert(errorTitle, errorMessage);

            return;
        }

        var url = this.generateUrlForGetAllLabelsFromOrderAction(orderId);
        window.open(url, '_blank');
    },

    /**
     * Generates a action url.
     *
     * @param orderId
     * @return string
     */
    generateUrlForGetAllLabelsFromOrderAction: function (orderId) {
        if (!this.mergedLabelsFromOrderActionUrl) {
            throw new Error('Action url needs to be defined');
        }

        return this.mergedLabelsFromOrderActionUrl + '?orderId=' + orderId;
    },

    /**
     * Define panel constraints here if the creation of tab.js needs it
     */
    addCreationPanelConstraints: function() {
        var me = this;

        // If we override the default labelConfirmWindow inside a Adapter use it
        // otherwise use the default one
        me.labelConfirmWindow = me.labelConfirmWindow || 'Shopware.apps.ViisonShippingCommonOrder.view.detail.LabelConfirmWindow';
    },

    /**
     * Wait until the dialog is actually shown (not doing so will lead to the dialog not being opened
     * when using firefox).
     */
    onAfterRender: function(orderDetailDialog) {
        orderDetailDialog.on('show', this.onAfterShow, this, {
            single: true
        });
    },

    /**
     * If the dispatch service provider tab shall be selected, this method will try to find it
     * in all tabs and select it.
     *
     * @param tabPanel The panel holding all tabs of the details view.
     */
    onAfterShow: function(orderDetailDialog) {
        var me = this;
        var tabPanel = orderDetailDialog.down('tabpanel[name=main-tab]');

        var dispatchServiceProviderTab = tabPanel.down(me.dispatchServiceProviderPanelClass);
        var shippingLabelStore = dispatchServiceProviderTab.shippingLabelStore;

        shippingLabelStore.on('load', function(store) {
            // Update add button state
            me.updateAddLabelButton(dispatchServiceProviderTab);
        }, this, {
            single: true
        });

        // Check if the label confirm window of this tab should be shown
        if (me.subApplication.params && me.subApplication.params.focus == me.dispatchServiceProviderPanelClass && me.subApplication.params.showLabelConfirmWindow) {
            var openLabelConfirmWindow = function() {
                // Trigger the label confirm window
                me.onShowLabelConfirmWindow(dispatchServiceProviderTab, tabPanel.up('order-detail-window').record, shippingLabelStore);
            };

            if (shippingLabelStore.isLoaded) {
                openLabelConfirmWindow();
            } else {
                shippingLabelStore.on('load', function() {
                    openLabelConfirmWindow();
                }, this, {
                    single: true
                });
            }
        }
    },

    /**
     * Updates the state and the tooltip of the 'add label' button in the dispatch service provider tab
     * based on the number of shipping labels in the store.
     *
     * @param dispatchServiceProviderTab The dispatch service provider panel for which the add label button should be updated.
     */
    updateAddLabelButton: function(dispatchServiceProviderTab) {
        var button = dispatchServiceProviderTab.addLabelButton;
        var disable = (dispatchServiceProviderTab.shippingLabelStore.count() >= this.maxNumberOfLabels);
        button.setDisabled(disable);
        button.setTooltip((!disable) ? button.enabledTooltip : button.disabledTooltip);
    },

    /**
     * Updates the tracking codes in the main record as well as the
     * corresponding form field.
     *
     * @param dispatchServiceProviderTab The dispatch service provider tab that is part of the window in which the tracking codes should be updated.
     * @param record
     * @param newTrackingCodes A string consisting of the old as well as the new tracking codes.
     */
    updateOrderTrackingCodes: function(dispatchServiceProviderTab, record, newTrackingCodes) {
        var orderDetailWindow = dispatchServiceProviderTab.up('order-detail-window');

        // Update tracking code(s) in record
        record.set('trackingCode', newTrackingCodes);

        // Update tracking code(s) form fields
        var trackingCodeField = orderDetailWindow.down('order-overview-panel [name=\'trackingCode\']');

        if (trackingCodeField) {
            trackingCodeField.setValue(newTrackingCodes);
        }
    },

    /**
     * Updates the undispatched tracking codes in the main record as well as the corresponding form field.
     * This attribute and the form field only exist when Pickware is installed.
     *
     * @param dispatchServiceProviderTab The dispatch service provider tab that is part of the window in which the tracking codes should be updated.
     * @param record
     * @param newTrackingCodes A string consisting of the old as well as the new tracking codes.
     */
    updateOrderUndispatchedTrackingCodes: function(dispatchServiceProviderTab, record, newTrackingCodes) {
        var orderDetailWindow = dispatchServiceProviderTab.up('order-detail-window');

        // Update undispatched tracking code(s) in record
        record.set('viisonUndispatchedTrackingCodes', newTrackingCodes);

        // Update tracking code(s) form fields
        var trackingCodeField = orderDetailWindow.down('order-overview-panel [name=\'viisonUndispatchedTrackingCodes\']');

        if (trackingCodeField) {
            trackingCodeField.setValue(newTrackingCodes);
        }
    },

    /**
     * Updates the shipping address in the main record as well as the
     * corresponding form fields.
     *
     * @param orderDetailWindow The window in which the shipping address should be updated.
     * @param record
     * @param newAddress An object containing the new address values.
     */
    updateOrderShippingAddress: function(orderDetailWindow, record, newAddress) {
        // Update shipping address in record
        var shippingRecord = record.getShipping().findRecord('orderId', record.getId());
        shippingRecord.set(newAddress);

        // Update shipping address form fields
        var detailPanel = orderDetailWindow.down('component[cls=' + Ext.baseCSSPrefix + 'detail-panel]');
        if (detailPanel) {
            var shippingForm = detailPanel.items.findBy(function(item, key) {
                return item.id.indexOf('shipping-field-set') !== -1;
            });
            // Update the values of all fields
            shippingForm.items.each(function(item) {
                item.items.each(function(innerItem) {
                    var key = innerItem.name.substring(innerItem.name.indexOf('[')+1, innerItem.name.length-1);
                    innerItem.setValue(shippingRecord.get(key));
                });
            });
        }
    },

    /**
     * This method is executed before the order detail window is opened for the given order.
     *
     * @param record
     */
    onShowOrder: function(record) {
        this.loadDataForOrder(record);
    },

    /**
     * Loads the dispatch service provider specific data into the order record and updates the label confirm
     * window if one exists.
     *
     * @param record
     */
    loadDataForOrder: function(record) {
        var me = this;

        if (!record) {
            return;
        }

        // Older plugins do not yet have a getShippingOrderDataURL property, if it is missing use getProductURL, which already existed before
        if ('getShippingOrderDataURL' in me) {
            var shippingOrderDataURL = me.getShippingOrderDataURL;
        } else {
            var shippingOrderDataURL = me.getProductURL.replace('getProduct', 'getShippingOrderData');
        }

        Ext.Ajax.request({
            url: shippingOrderDataURL,
            params: {
                orderId: record.getId()
            },
            success: function(response) {
                var data = Ext.JSON.decode(response.responseText).data;

                // Update shipment weight
                me.updateOrderWeight(record, data.shippingWeight);
                record[me.dispatchServiceProviderPrefix] = record[me.dispatchServiceProviderPrefix] || {};
                record[me.dispatchServiceProviderPrefix].splittedAddress = data.splitAddress;
                record[me.dispatchServiceProviderPrefix].fieldConstraints = data.requiredFields;
                record[me.dispatchServiceProviderPrefix] = Ext.apply(record[me.dispatchServiceProviderPrefix], data.product);
                record[me.dispatchServiceProviderPrefix].isCashOnDelivery = data.isCashOnDelivery;
                record[me.dispatchServiceProviderPrefix] = Ext.apply(record[me.dispatchServiceProviderPrefix], data.defaultPackageDimensions);
                record[me.dispatchServiceProviderPrefix].isCustomerMailTransferAllowed = data.isCustomerMailTransferAllowed;
                record[me.dispatchServiceProviderPrefix].isCustomerPhoneTransferAllowed = data.isCustomerPhoneTransferAllowed;

                me.handleCustomShippingOrderData(record, data);

                if (me.getLabelConfirmWindow() && me.getLabelConfirmWindow().dataPanel) {
                    // Force update of displayed values in label confirm view
                    me.getLabelConfirmWindow().dataPanel.setValues();
                    me.getLabelConfirmWindow().dataPanel.updatePhoneEmailDisabledState();
                }
            }
        });
    },

    /**
     * Can be overridden in dispatch service provider plugins to handle custom shipping order data.
     */
    handleCustomShippingOrderData: function(record, data) {

    },

    /**
     * Load order address data into the form
     *
     * @param dispatchServiceProviderTab
     * @param record
     */
    onShowLabelConfirmWindow: function (dispatchServiceProviderTab, record) {
        this.callParent(arguments);

        this.loadDataForOrder(record);
    },

});
