// 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 for creating and deleting
 * shipping labels. It is inherited by the dispatch service provider panels and in the
 * free form label generation dialogs.
 */
//{namespace name="backend/viison_shipping_common_order/shipping_labels"}
Ext.define('Shopware.apps.ViisonShippingCommonOrder.controller.ShippingLabels', {

    extend: 'Ext.app.Controller',

    snippets: {
        notifications: {
            createLabelSuccess: {
                title: '{s name="shipping_labels/notifications/create_label_success/title"}{/s}',
                message: '{s name="shipping_labels/notifications/create_label_success/message"}{/s}'
            },
            createLabelError: {
                title: '{s name="shipping_labels/notifications/create_label_error/title"}{/s}',
                message: '{s name="shipping_labels/notifications/create_label_error/message"}{/s}'
            },
            destroyLabelConfirmationWindow: {
                title: '{s name="shipping_labels/notifications/destroy_popup/title"}{/s}',
                message: '{s name="shipping_labels/notifications/destroy_popup/message"}{/s}',
                btnText: '{s name="shipping_labels/notifications/destroy_popup/btn_text"}{/s}',
            },
            destroyLabelSuccess: {
                title: '{s name="shipping_labels/notifications/destroy_label_success/title"}{/s}',
                message: '{s name="shipping_labels/notifications/destroy_label_success/message"}{/s}'
            },
            destroyLabelWithRevokeSuccess : {
                title: '{s name="shipping_labels/notifications/destroy_label_revoked_success/title"}{/s}',
                message: '{s name="shipping_labels/notifications/destroy_label_revoked_success/message"}{/s}'
            },
            destroyLabelError: {
                title: '{s name="shipping_labels/notifications/destroy_label_error/title"}{/s}',
                message: '{s name="shipping_labels/notifications/destroy_label_error/message"}{/s}'
            },
            destroyLabelErrorSticky: {
                title: '{s name="shipping_labels/notifications/destroy_label_error_sticky/title"}{/s}',
                buttonTitle: '{s name="shipping_labels/notifications/destroy_label_error_sticky/button_title"}{/s}',
                message: '{s name="shipping_labels/notifications/destroy_label_error_sticky/message"}{/s}',
                messageAddition: '{s name="shipping_labels/notifications/destroy_label_error_sticky/message_addition"}{/s}'
            },
            invalidFormError: {
                title: '{s name="shipping_labels/notifications/invalid_form_error/title"}{/s}',
                message: '{s name="shipping_labels/notifications/invalid_form_error/message"}{/s}'
            },
            limitReachedInfo: {
                title: '{s name="shipping_labels/notifications/limit_reached_info/title"}{/s}',
                message: '{s name="shipping_labels/notifications/limit_reached_info/message"}{/s}'
            },
            sendReturnLabelEmailSuccess: {
                title: '{s name="shipping_labels/notifications/send_return_label_email_success/title"}{/s}',
                message: '{s name="shipping_labels/notifications/send_return_label_email_success/message"}{/s}'
            },
            sendReturnLabelEmailError: {
                title: '{s name="shipping_labels/notifications/send_return_label_email_error/title"}{/s}',
                message: '{s name="shipping_labels/notifications/send_return_label_email_error/message"}{/s}'
            }
        }
    },

    /**
     * @var boolean
     * @default false
     *
     * Flag to tell if the label is also revoked/canceled by the delete process.
     *
     * NOTE: Every adapter that supports this, needs to set the flag to true
     */
    additionalFlags: {
        isLabelCanceledByDeleteProcess: false
    },

    /**
     * Add a reference to the label confirm and mail windows
     */
    constructor: function() {
        this.refs = (this.refs || []).concat([{
                ref: 'labelConfirmWindow',
                selector: 'order-viison-shipping-common-label-confirm-window'
            },
            {
                ref: 'labelConfirmPanel',
                selector: 'order-viison-shipping-common-label-confirm-panel'
            },
            {
                ref: 'mailWindow',
                selector: 'order-viison-shipping-common-mail-window'
            }
        ]);
        this.callParent(arguments);
    },

    init: function() {
        var me = this;

        me.control(me.labelPanelSelector, {
            showLabelConfirmWindow: me.onShowLabelConfirmWindow,
            showReturnLabelConfirmWindow: me.onShowReturnLabelConfirmWindow
        });

        me.control(me.labelPanelSelector + ' panel[itemId=labelShipmentGrid]', {
            trackShippingLabel: me.onTrackShippingLabel,
            destroyShippingLabel: me.onDestroyShippingLabel
        });

        me.control(me.dispatchServiceProviderLabelConfirmPanel, {
            createShippingLabel: me.onCreateShippingLabel,
            createReturnLabel: me.addReturnLabel,
            destroyLabelConfirmWindow: me.onDestroyLabelConfirmWindow
        });

        me.control('order-viison-shipping-common-mail[cls="'+me.dispatchServiceProviderCSSClass+'"] button[action=cancel]', {
            click: me.onCancelSendReturnLabelMail
        });

        me.control('order-viison-shipping-common-mail[cls="'+me.dispatchServiceProviderCSSClass+'"]', {
            sendReturnLabelMail: me.onSendReturnLabelMail
        });
    },

    /**
     * Displays a window in which the label parameters can be set and the receiver address can be changed.
     *
     * @param dispatchServiceProviderTab The dispatch service provider panel where the add label button was clicked.
     * @param record The record whose detail view is active.
     * @param shippingLabelStore The store handling all shipping labels of the record.
     */
    onShowLabelConfirmWindow: function(dispatchServiceProviderTab, record, shippingLabelStore) {
        var me = this;

        // Recalculate the order weight since the order positions might have been changed in the meantime
        me.updateOrderWeightAjax(record);

        // Destroy old window
        if (me.getLabelConfirmWindow() !== undefined) {
            me.getLabelConfirmWindow().destroy();
        }

        // Check if window should be opened depending on the number of already created labels
        if (shippingLabelStore.count() >= me.maxNumberOfLabels) {
            var notification = me.snippets.notifications.limitReachedInfo;
            var message = notification.message.replace('#LIMIT#', me.maxNumberOfLabels);
            Shopware.Notification.createGrowlMessage(notification.title, message, me.dispatchServiceProviderPrefix);
            return;
        }

        // Create new window
        // Note: me.labelConfirmWindow will only be set if the approach implements tab.js controller or if
        //       we set the value inside the free form labels main.js files from the adapters
        //       otherwise we use the default LabelConfirmWindow view
        Ext.create(me.labelConfirmWindow || 'Shopware.apps.ViisonShippingCommonOrder.view.detail.LabelConfirmWindow', {
            record: record,
            store: shippingLabelStore,
            maxNumberOfLabels: me.maxNumberOfLabels,
            dispatchServiceProviderTab: dispatchServiceProviderTab,
            labelConfirmPanelClass: me.labelConfirmPanelClass,
            subApp: me.subApplication,
            orderConfigData: (me.orderConfigDataClass) ? (Ext.getStore(me.orderConfigDataClass) || Ext.create(me.orderConfigDataClass)) : null,
            productStore: Ext.create(me.productStoreClass).load({
                // Send always the shopId as a Param
                scope: record,
                params: {
                    shopId: record ? record.get('shopId') : null
                }
            })
        }).show();
    },

    /**
     * Displays a window in which the return label parameters can be set and the sender address can be changed.
     *
     * @param dispatchServiceProviderTab The dispatch service provider panel where the add label button was clicked.
     * @param record The record whose detail view is active.
     * @param shippingLabelStore The store handling all shipping labels of the record.
     */
    onShowReturnLabelConfirmWindow: function(dispatchServiceProviderTab, record, shippingLabelStore) {
        var me = this;

        // Destroy old window
        if (me.getLabelConfirmWindow() !== undefined) {
            me.getLabelConfirmWindow().destroy();
        }

        // Create new window
        Ext.create(me.labelConfirmWindow || 'Shopware.apps.ViisonShippingCommonOrder.view.detail.LabelConfirmWindow', {
            record: record,
            store: shippingLabelStore,
            maxNumberOfLabels: me.maxNumberOfLabels,
            dispatchServiceProviderTab: dispatchServiceProviderTab,
            productStore: Ext.create(me.productStoreClass).load(),
            labelConfirmPanelClass: me.labelConfirmPanelClass,
            subApp: me.subApplication,
            isReturn: true,
            orderConfigData: (me.orderConfigDataClass) ? (Ext.getStore(me.orderConfigDataClass) || Ext.create(me.orderConfigDataClass)) : null
        }).show();
    },

    /**
     * Creates a return label and displays the 'send email' window.
     *
     * @param dispatchServiceProviderTab The dispatch service provider panel where the add return label button was clicked.
     * @param record The record whose detail view is active.
     */
    addReturnLabel: function(dispatchServiceProviderTab, record, details, packagingDetails, settings, extraSettings, confirmWindow) {
        var me = this;

        if (!me.verifyForm(confirmWindow)) {
            return;
        }

        var params = me.getShippingLabelParams(record ? record.getId() : null, details, packagingDetails, settings, extraSettings);
        params.returnShipment = true;

        // Create new label
        var label = Ext.create(me.shippingLabelClass, params);

        confirmWindow.loadMask.show();

        // Add to store
        label.save({
            callback: function(data, operation) {

                if (operation.success !== true || data.get('creationSuccess') !== true) {
                    confirmWindow.loadMask.hide();
                    // Show error description
                    var notification = me.snippets.notifications.createLabelError;
                    var message = (data.get('message') && data.get('message').length > 0) ? data.get('message') : notification.message;
                    Shopware.Notification.createGrowlMessage(notification.title, message, me.dispatchServiceProviderPrefix);
                    return;
                } else {
                    // Success
                    confirmWindow.destroy();
                }

                var notification = me.snippets.notifications.createLabelSuccess;
                Shopware.Notification.createGrowlMessage(notification.title, notification.message, me.dispatchServiceProviderPrefix);

                // Refresh label store and list
                me.refreshLabelLists();

                // Destroy old window
                if (me.getMailWindow() !== undefined) {
                    me.getMailWindow().destroy();
                }

                // Display a new email window
                Ext.create('Shopware.apps.ViisonShippingCommonOrder.view.detail.MailWindow', {
                    labelId: label.get('id'),
                    mail: data.getProxy().getReader().rawData.data.mail,
                    cls: me.dispatchServiceProviderCSSClass,
                    subApp: me.subApplication
                }).show();
            }
        });
    },

    /**
     * Creates a new shipping label (or multiple with the same parameters) and adds them to the list.
     *
     * @param dispatchServiceProviderTab The dispatch service provider panel in which the user opened the label confirm window.
     * @param record The record the new label(s) should be added to.
     * @param store The store handling all shipping labels of the record.
     * @param details The form data containing all shipping details to use for the label(s).
     * @param packagingDetails The form data containing e.g. the dimension of the package.
     * @param settings The form data containing all settings to use for the label(s).
     * @param confirmWindow The window firing the handled event.
     */
    onCreateShippingLabel: function(dispatchServiceProviderTab, record, details, packagingDetails, settings, extraSettings, confirmWindow) {
        var me = this;

        // Increase AJAX timeout from default 30 seconds to 60 seconds (sometimes, DHL is extremely slow)
        Ext.override(Ext.data.proxy.Ajax, { timeout: 60000 });

        if (!me.verifyForm(confirmWindow)) {
            return;
        }

        // Show the loading mask of the confirm window
        if (confirmWindow !== undefined) {
            confirmWindow.loadMask.show();
        }

        // Define a callback, which is triggered only after all requests are finished
        var labelCreationResult = {
            closeWindow: true,
            newTrackingCodes: [],
            newDocumentIdentifiers: []
        };

        var afterFinished = me.after(settings.numberOfLabels, function() {
            me.afterLabelCreationFinished(dispatchServiceProviderTab, record, details, confirmWindow, labelCreationResult);
        });

        for (var i = 0; i < settings.numberOfLabels; i++) {
            var shippingLabelParams = me.getShippingLabelParams(record ? record.getId() : null, details, packagingDetails, settings, extraSettings);

            me.createLabel(shippingLabelParams, labelCreationResult, afterFinished);
        }
    },

    verifyForm: function(confirmWindow) {
        var me = this;

        // Check validity of the forms
        if (!confirmWindow.down('panel').getForm().isValid()) {
            // Invalid
            var notification = me.snippets.notifications.invalidFormError;
            Shopware.Notification.createGrowlMessage(notification.title, notification.message, me.dispatchServiceProviderPrefix);
            return false;
        }
        return true;
    },

    /**
     * Closes the given LabelConfirmWindow.
     *
     * @param confirmWindow The window firing the handled event.
     */
    onDestroyLabelConfirmWindow: function(confirmWindow) {
        if (confirmWindow !== undefined) {
            confirmWindow.destroy();
        }
    },

    /**
     * Deletes the given label from the dispatch service provider system and removes it from the store.
     *
     * @param dispatchServiceProviderPanel The active dispatch service provider panel.
     * @param record The order record the label should be removed from.
     * @param label The record of the label that should be deleted.
     * @param store The store handling all shipping labels of the record.
     * @param onlyLocal A boolean indicating that the label shall be only removed from the database and the file system (e.g. when the dispatch service provider web service is down).
     */
    onDestroyShippingLabel: function(dispatchServiceProviderPanel, record, label, store, onlyLocal) {
        var snippet = this.snippets.notifications.destroyLabelConfirmationWindow;

        // Ask user to confirm the delete process
        Ext.Msg.confirm(snippet.title, snippet.message, function(buttonId) {
            if (buttonId !== 'yes') {
                return;
            }

            this.proceedWithDestroyShippingLabel(dispatchServiceProviderPanel, record, label, store, onlyLocal);
        }, this);
    },

    proceedWithDestroyShippingLabel: function(dispatchServiceProviderPanel, record, label, store, onlyLocal) {
        var me = this;

        // Request deletion
        dispatchServiceProviderPanel.loadMask.show();
        label.destroy({
            params: {
                onlyLocal: onlyLocal
            },
            callback: function(data, operation) {
                var json;
                dispatchServiceProviderPanel.loadMask.hide();
                var success = false;

                if (!operation.success) {
                    var errorData = data.getProxy().getReader().rawData;
                    if (errorData && errorData.exception) {
                        // Retrieve adapter error message from the API.
                        json = errorData;
                        success = errorData.success;
                    }
                }

                // Get real status information from plain json response
                // Backwards compatibility and old adapter compatibility
                if (operation.response && operation.response.responseText && operation.response.responseText.length > 0) {
                    // Decode JSON response and update success status
                    json = Ext.JSON.decode(operation.response.responseText);
                    if (json && json.status && json.status.success) {
                        success = json.status.success;
                    }
                }

                // Handle the response
                if (success === true) {
                    // Refresh label store and list
                    me.refreshLabelLists();

                    // Remove tracking code from string displayed in the order overview
                    var trackingCode = label.get('trackingCode');

                    // Check if product supports tracking code
                    if (trackingCode) {
                        var re = new RegExp(trackingCode, 'g');
                        if (record) {
                            var newTrackingCodeString = record.data.trackingCode.replace(re, '').replace(/(^,)|(,$)/, '').replace(/,,/, ',');
                            me.updateOrderTrackingCodes(dispatchServiceProviderPanel, record, newTrackingCodeString);
                            if (record.data.viisonUndispatchedTrackingCodes) {
                                var newUndispatchedTrackingCodeString = record.data.viisonUndispatchedTrackingCodes.replace(re, '').replace(/(^,)|(,$)/, '').replace(/,,/, ',');
                                me.updateOrderUndispatchedTrackingCodes(dispatchServiceProviderPanel, record, newUndispatchedTrackingCodeString);
                            }
                        }
                    }

                    // Show success notification
                    var notification = me.additionalFlags.isLabelCanceledByDeleteProcess ? me.snippets.notifications.destroyLabelWithRevokeSuccess : me.snippets.notifications.destroyLabelSuccess;
                    Shopware.Notification.createGrowlMessage(notification.title, notification.message, me.dispatchServiceProviderPrefix);
                } else if (onlyLocal === true) {
                    // Show error description in default notification
                    var notification = me.additionalFlags.isLabelCanceledByDeleteProcess ? me.snippets.notifications.destroyLabelWithRevokeSuccess : me.snippets.notifications.destroyLabelSuccess;
                    var message = (json && json.status && json.status.message && json.status.message.length > 0) ? json.status.message : notification.message;
                    Shopware.Notification.createGrowlMessage(notification.title, message, me.dispatchServiceProviderPrefix);
                } else {
                    // Show a sticky error notification allowing the user to force a deletion of the label from database
                    var notification = me.snippets.notifications.destroyLabelErrorSticky;
                    var message = (json && json.status && json.status.message && json.status.message.length > 0) ? json.status.message : notification.message;
                    message += '<br><br>' + notification.messageAddition;
                    // Create the growl notification
                    var growlMsg = Shopware.Notification.createStickyGrowlMessage({
                        title: notification.title,
                        text: message,
                        width: 450,
                        btnDetail: {
                            text: notification.buttonTitle,
                            scope: me,
                            link: '-'
                        }
                    });

                    // Replace the default handler of the custom button to just perform a callback
                    growlMsg.getComponent(1).getComponent(0).setHandler(function() {
                        // Force the deletion of the label
                        me.onDestroyShippingLabel(dispatchServiceProviderPanel, record, label, store, true);
                        // Close the notification
                        Shopware.Notification.closeGrowlMessage(growlMsg, Shopware.Notification);
                    });
                }
            }
        });
    },

    /**
     * Closes the mail window.
     */
    onCancelSendReturnLabelMail: function(button, event, options) {
        if (this.getMailWindow()) {
            this.getMailWindow().destroy();
        }
    },

    /**
     * Checks the mail form for its validity and, if valid, sends a new email.
     *
     * @param mailForm The form containing the receivers email address, the subject and the content of the mail.
     */
    onSendReturnLabelMail: function(mailForm) {
        var me = this;

        // Check if all fields are valid
        if (!mailForm.getForm().isValid()) {
            return;
        }

        // Show the load mask
        me.getMailWindow().loadMask.show();

        // Send the email
        Ext.Ajax.request({
            url: me.sendMailURL,
            method: 'POST',
            jsonData: {
                labelId: mailForm.labelId,
                mail: mailForm.getForm().getFieldValues()
            },
            scope: this,
            callback: function(options, success, response) {
                // Hide the load mask
                me.getMailWindow().loadMask.hide();
                // Get real status information from plain json response
                success = false;
                if (response && response.responseText && response.responseText.length > 0) {
                    // Decode JSON response and update success status
                    var json = Ext.JSON.decode(response.responseText);
                    if (json && json.success) {
                        success = json.success;
                    }
                }
                if (success) {
                    // Close the window
                    this.onCancelSendReturnLabelMail();
                    // Display a success notification
                    var notification = this.snippets.notifications.sendReturnLabelEmailSuccess;
                    Shopware.Notification.createGrowlMessage(notification.title, notification.message, me.dispatchServiceProviderPrefix);
                } else {
                    // Display an error notification
                    var notification = this.snippets.notifications.sendReturnLabelEmailError;
                    Shopware.Notification.createGrowlMessage(notification.title, notification.message, me.dispatchServiceProviderPrefix);
                }
            }
        });
    },

    /**
     * Opens a new tab/window showing the DHL shipment tracking of the given label.
     *
     * @param label The label which should be tracked.
     */
    onTrackShippingLabel: function(label) {
        var trackingCode = label.get('trackingCode');
        this.getController('Shopware.apps.ViisonShippingCommonOrder.controller.ListDispatch').openTrackingWindows(trackingCode);
    },

    /**
     * This function is called after all label creation request are finished.
     */
    afterLabelCreationFinished: function(dispatchServiceProviderTab, record, details, confirmWindow, labelCreationResult) {
        var me = this;

        // Decide whether to close the creation window or its loading mask
        if (confirmWindow !== undefined) {
            if (labelCreationResult.closeWindow) {
                confirmWindow.destroy();
            } else {
                confirmWindow.loadMask.hide();
            }
        }

        if (record) {
            // Update tracking codes
            var newTrackingCodeString = record.data.trackingCode;
            if (newTrackingCodeString.length > 0 && labelCreationResult.newTrackingCodes.length > 0) {
                newTrackingCodeString += ',';
            }
            newTrackingCodeString += labelCreationResult.newTrackingCodes.join(',');

            me.updateOrderTrackingCodes(dispatchServiceProviderTab, record, newTrackingCodeString);

            if (details.saveInOrder) {
                var orderDetailWindow = dispatchServiceProviderTab.up('order-detail-window');
                // Update shipping address
                var newAddressData = {
                    salutation: details.salutation,
                    firstName: details.firstName,
                    lastName: details.lastName,
                    company: details.company,
                    department: details.department,
                    street: details.street,
                    streetNumber: details.streetNumber,
                    zipCode: details.zipCode,
                    city: details.city,
                    countryId: details.country,
                };
                // Only update phone/email if they are not disabled because customer contact data transfer is not allowed
                if (details.email !== undefined) {
                    newAddressData.email = details.email;
                }
                if (details.phone !== undefined) {
                    newAddressData.phone = details.phone;
                }
                me.updateOrderShippingAddress(orderDetailWindow, record, newAddressData);
            }

            // Reload all order list panels so that the new tracking codes get included in their data
            Ext.each(Ext.ComponentQuery.query('order-list'), function(orderList) {
                orderList.store.reload();
            });
        }

        // Download the created shipping labels
        // Backwards compatibility until we set all Adapters to use documentIdentifier
        var downloadParameters = (labelCreationResult.newDocumentIdentifiers.length) ?
            labelCreationResult.newDocumentIdentifiers :
            labelCreationResult.newTrackingCodes;

        Ext.each(downloadParameters, function (downloadParameter) {
            Ext.Ajax.request({
                url: me.downloadDocumentsURL,
                method: 'GET',
                params: {
                    labelIdentifier: downloadParameter
                }
            });
        });

        // Reset AJAX timeout to the default (30 seconds)
        Ext.override(Ext.data.proxy.Ajax, { timeout: 30000 });
    },

    /**
     * @source http://underscorejs.org/docs/underscore.html
     */
    after: function(times, func) {
        return function() {
            if (--times < 1) {
                return func.apply(this, arguments);
            }
        };
    },

    /**
     *
     * @param details
     * @param packagingDetails
     * @param settings
     */
    getShippingLabelParams: function(orderId, details, packagingDetails, settings, extraSettings) {
        var params = {
            orderId: orderId,
            detailsStateId: details.state,
            detailsCountryId: details.country
        };

        Ext.iterate(details, function(key, value) {
            params['details' + key.charAt(0).toUpperCase() + key.slice(1)] = value;
        });

        if (packagingDetails) {
            Ext.apply(params, {
                packagingLength: packagingDetails.packagingLength,
                packagingWidth: packagingDetails.packagingWidth,
                packagingHeight: packagingDetails.packagingHeight,
                packagingWeight: packagingDetails.weight
            });
        }

        if (settings) {
            Ext.apply(params, {
                settingsProduct: settings.product,
                settingsCashOnDelivery: settings.cashOnDelivery,
                settingsCreateExportDocument: settings.createExportDocument,
                settingsSaveInOrder: details.saveInOrder
            });
        };

        if (extraSettings) {
            Ext.iterate(extraSettings, function(key, value) {
                params['extraSettings' + key.charAt(0).toUpperCase() + key.slice(1)] = value;
            });
        }

        return params;
    },

    /**
     * Updates the order weight in the record to the given updated value.
     *
     * @param record The record representing the order.
     */
    updateOrderWeight: function(record, data) {
        var me = this;
        record[me.dispatchServiceProviderPrefix] = record[me.dispatchServiceProviderPrefix] || {};
        record[me.dispatchServiceProviderPrefix].calculatedShipmentWeight = {
            weight: data.weight,
            complete: !data.orderHasItemsWithoutWeight,
            isDefault: data.isDefault
        }
    },

    /**
     * Requests the total shipment weight of the given order, adds it to
     * its record and triggers an update of the values in the label confirm window.
     *
     * @param record The record representing the order.
     */
    updateOrderWeightAjax: function(record) {
        if (!record) {
            return;
        }

        var me = this;
        Ext.Ajax.request({
            url: me.calculateShippingWeightURL,
            params: {
                orderId: record.getId()
            },
            success: function(response) {
                var data = Ext.JSON.decode(response.responseText);
                if (data.success) {
                    me.updateOrderWeight(record, data);
                } else {
                    // Remove a potential previously calculated Weight
                    delete record[me.dispatchServiceProviderPrefix].calculatedShipmentWeight;
                }

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

    refreshLabelLists: function() {
        var me = this;

        var dispatchServiceProviderPanels = Ext.ComponentQuery.query(me.dispatchServiceProviderPanelClass);
        Ext.each(dispatchServiceProviderPanels, function(panel) {
            panel.shippingLabelStore.load({
                callback: function(records, operation, success) {
                    // Because we have the deprecated label grid and the new label shipment grid
                    // we are accessing the component via the itemId that is same.
                    var labelGrid = panel.down('panel[itemId=labelShipmentGrid]');
                    labelGrid.getView().refresh();
                }
            });
        });
    },

    createLabel: function(shippingLabelParams, labelCreationResult, afterFinish) {
        var me = this;
        var success = false;

        // Create new label
        var label = Ext.create(me.shippingLabelClass, shippingLabelParams);

        // Add to store
        label.save({
            callback: function(data, operation) {
                if (operation.success === true && data.get('creationSuccess') === true) {
                    // Refresh label store and list
                    me.refreshLabelLists();
                    var notification = me.snippets.notifications.createLabelSuccess;
                    Shopware.Notification.createGrowlMessage(notification.title, notification.message, me.dispatchServiceProviderPrefix);

                    if (data.get('warningMessageForCashOnDelivery')) {
                        Shopware.Notification.createGrowlMessage(null, data.get('warningMessageForCashOnDelivery'), me.dispatchServiceProviderPrefix);
                    }

                    labelCreationResult.newTrackingCodes.push(data.get('trackingCode'));
                    success = true;
                } else {
                    me.handleLabelCreationError(data.get('message'), data.get('errorCode'));

                    // Prevent the creation window from being closed
                    labelCreationResult.closeWindow = false;
                }

                // Mark this request as finished
                afterFinish.call(me);
            }
        });

        return success;
    },

    handleLabelCreationError: function(message, errorCode) {
        var me = this;

        // Show error description
        var notification = me.snippets.notifications.createLabelError;
        var message = (message && message.length > 0) ? message : notification.message;
        Shopware.Notification.createGrowlMessage(notification.title, message, me.dispatchServiceProviderPrefix);
    }

});
