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

/**
 * The main panel of the LabelConfirmWindow containing all form fields, which hold the shipping details
 * and settings of this record(order). Furthermore two buttons (cancel, confirm) are added.
 */
//{namespace name="backend/viison_shipping_common_order/order"}
Ext.define('Shopware.apps.ViisonShippingCommonOrder.view.detail.LabelConfirm', {

    /**
     * Extend from the standard ExtJS 4.
     */
    extend: 'Ext.form.Panel',

    /**
     * List of short aliases for class names. Most useful for defining xtypes for widgets.
     */
    alias: 'widget.order-viison-shipping-common-label-confirm-panel',

    /**
     * Component layout definition.
     */
    layout: {
        align: 'stretch',
        type: 'vbox'
    },

    /**
     * Set flex to 100%.
     */
    flex: 1,

    /**
     * Add padding.
     */
    bodyPadding: '10 10 0 10',

    /**
     * Remove the border.
     */
    border: 0,

    /**
     * Disable collapse mode.
     */
    collapsible: false,

    fieldConstraints: {
        packageDimensionsRequired: false
    },

    /**
     * Display package dimensions by default, can be changed in subclasses by individual shipping provider plugins
     */
    displayPackagingDimensionFields: true,

    /**
     * Contains all snippets for the view component.
     */
    snippets: {
        details: {
            title: '{s name="label_confirm/details/title"}{/s}',
            labels: {
                salutation: {
                    label: '{s name="label_confirm/details/labels/salutation/label"}{/s}',
                    mr: '{s name="label_confirm/details/labels/salutation/salutation_mr"}{/s}',
                    ms: '{s name="label_confirm/details/labels/salutation/salutation_ms"}{/s}',
                    company: '{s name="label_confirm/details/labels/salutation/salutation_company"}{/s}',
                    help: '{s name="label_confirm/details/labels/salutation/help"}{/s}'
                },
                saveInOrder: '{s name="label_confirm/details/labels/save_in_order"}{/s}',
                companyAndDepartment: '{s name="label_confirm/details/labels/company_and_department"}{/s}',
                name: '{s name="label_confirm/details/labels/name"}{/s}',
                streetAndNumber: '{s name="label_confirm/details/labels/street_and_number"}{/s}',
                additionalAddressLine: '{s name="label_confirm/details/labels/additional_address_line"}{/s}',
                additionalAddressLineOnly: '{s name="label_confirm/details/labels/additional_address_line_only"}{/s}',
                zipCityAndCountry: '{s name="label_confirm/details/labels/zip_city_and_country"}{/s}',
                phone: '{s name="label_confirm/details/labels/phone"}{/s}',
                email: '{s name="label_confirm/details/labels/email"}{/s}'
            }
        },
        packagingDetails: {
            title: '{s name="label_confirm/packaging_details/title"}{/s}',
            titleWithoutDimensions: '{s name="label_confirm/packaging_details/title_without_dimensions"}{/s}',
            labels: {
                length: '{s name="label_confirm/packaging_details/labels/length"}{/s}',
                width: '{s name="label_confirm/packaging_details/labels/width"}{/s}',
                height: '{s name="label_confirm/packaging_details/labels/height"}{/s}',
                weight: '{s name="label_confirm/packaging_details/labels/weight"}{/s}'
            }
        },
        settingsDetails: {
            title: '{s name="label_confirm/settings_details/title"}{/s}',
            labels: {
                createExportDocument: '{s name="label_confirm/settings_details/labels/create_export_document"}{/s}',
                cashOnDelivery: '{s name="label_confirm/settings_details/labels/cash_on_delivery"}{/s}',
                numberOfLabels: '{s name="label_confirm/settings_details/labels/number_of_labels"}{/s}',
                saturdayDelivery:'{s name="label_confirm/settings_details/labels/saturday_delivery"}{/s}',
            }
        },
        orderAmountInformation: {
            title: '{s name="label_confirm/order_amount_information/title"}{/s}',
            labels: {
                amount: '{s name="label_confirm/order_amount_information/labels/amount"}{/s}',
                currency: '{s name="label_confirm/order_amount_information/labels/currency"}{/s}',
                insurance: '{s name="label_confirm/order_amount_information/labels/insurance"}{/s}'
            }
        },
        buttons: {
            confirm: '{s name="label_confirm/buttons/confirm"}{/s}',
            cancel: '{s name="label_confirm/buttons/cancel"}{/s}'
        },
        tooltips: {
            cashOnDeliveryHelp: '{s name="label_confirm/tooltips/cash_on_delivery_help"}{/s}',
            itemWeightsComplete: '{s name="label_confirm/tooltips/item_weights_complete"}{/s}',
            itemWeightsIncomplete: '{s name="label_confirm/tooltips/item_weights_incomplete"}{/s}',
            weightManuallyChanged: '{s name="label_confirm/tooltips/weight_manually_changed"}{/s}',
            numberOfLabelsWeightWarning: '{s name="label_confirm/tooltips/number_of_labels_weight_warning"}{/s}',
            saveInOrderHelp: '{s name="label_confirm/tooltips/save_in_order_help"}{/s}',
            createExportDocumentHelp: '{s name="label_confirm/tooltips/create_export_document_help"}{/s}',
            productMappingMissing: '{s name="label_confirm/tooltips/product_mapping_missing"}{/s}',
            saturdayDeliveryHelp: '{s name="label_confirm/tooltips/saturday_delivery_help"}{/s}',
            emailDisabledHelp: '{s name="label_confirm/tooltips/email_disabled_help"}{/s}',
            phoneDisabledHelp: '{s name="label_confirm/tooltips/phone_disabled_help"}{/s}',
        },
        streetValidationFailed: '{s name="label_confirm/street_validation_failed"}{/s}',
        nameValidationFailed: '{s name="label_confirm/name_validation_failed"}{/s}',
        groupValidationFailed: '{s name="label_confirm/group_validation_failed"}{/s}'
    },

    /**
     * The main initializer registering events and adding view components.
     */
    initComponent: function() {
        var me = this;
        me.salutationData = [
            ['mr', me.snippets.details.labels.salutation.mr],
            ['ms', me.snippets.details.labels.salutation.ms],
            ['company', me.snippets.details.labels.salutation.company]
        ];
        me.items = me.getItems();
        me.updateExtraContainersVisibility();
        me.dockedItems = [
            me.createButtonsContainer()
        ];

        if (me.record) {
            me.fieldConstraints = me.record[me.dispatchServiceProviderPrefix].fieldConstraints;
            if (me.settingsContainer && me.numberOfLabels) {
                // If we are creating a label for a specific record, fill in the form according to the order record data
                me.numberOfLabels.maxValue = me.maxNumberOfLabels - me.store.count();
            }
            me.setValues();
        } else {
            // Free form label generation mode
            me.countriesStore.load({
                callback: function() {
                    // Set the default country to Germany when the countries store is loaded
                    me.detailsContainer.getForm().setValues({
                        country: me.countriesStore.findRecord('iso', me.defaultCountryIsoCode()).get('id')
                    });
                }
            });
        }

        me.callParent(arguments);

        // Register a change listener for fields that have a validation group
        Ext.each(me.query('[group]'), function(field) {
            field.addListener('change', me.fieldChange);
        });

        this.updatePhoneEmailDisabledState();
    },

    /*
     * Disable the phone and email fields if customer data is not allowed to be transferred.
     */
    updatePhoneEmailDisabledState: function () {
        // ignore for free form label
        if (this.record === null) {
            return;
        }

        // Since phone and email configuration is handled by seperate config fields, we have to disable them separately
        this.updateEmailDisabledState();
        this.updatePhoneDisabledState();
    },

    /**
     * Enables or disables (and shows hint) the email text field which is handled by a shipping provider adapter config
     * field. If the adapter does not support this config field (value is not true), the text field is disabled.
     */
    updateEmailDisabledState: function () {
        var emailField = this.down('#emailField');
        if (emailField === null) {
            return;
        }

        var isCustomerMailTransferAllowed = this.record[this.dispatchServiceProviderPrefix].isCustomerMailTransferAllowed;
        emailField.setDisabled(!isCustomerMailTransferAllowed);
        if (!isCustomerMailTransferAllowed) {
            Ext.QuickTips.register({
                target: emailField.getEl(),
                text: this.snippets.tooltips.emailDisabledHelp,
                enabled: true,
                showDelay: 20,
                trackMouse: true,
                autoShow: true,
            });
        } else {
            Ext.QuickTips.unregister(emailField);
        }
    },

    /**
     * Enables or disables (and shows hint) the phone text field which is handled by a shipping provider adapter config
     * field. If the adapter does not support this config field (value is not true), the text field is disabled.
     */
    updatePhoneDisabledState: function () {
        var phoneField = this.down('#phoneField');
        if (phoneField === null) {
            return;
        }

        var isCustomerPhoneTransferAllowed = this.record[this.dispatchServiceProviderPrefix].isCustomerPhoneTransferAllowed;
        phoneField.setDisabled(!isCustomerPhoneTransferAllowed);
        if (!isCustomerPhoneTransferAllowed) {
            Ext.QuickTips.register({
                target: phoneField.getEl(),
                text: this.snippets.tooltips.phoneDisabledHelp,
                enabled: true,
                showDelay: 20,
                trackMouse: true,
                autoShow: true,
            });
        } else {
            Ext.QuickTips.unregister(phoneField);
        }
    },

    defaultCountryIsoCode: function() {
        return 'DE';
    },

    /**
     * Create the main form panel containing the details.
     *
     * @return The created panel.
     */
    createDetailsContainer: function() {
        var me = this;

        me.detailsContainer = Ext.create('Ext.form.Panel', {
            cls: 'confirm-panel-main',
            title: me.snippets.details.title,
            bodyPadding: 5,
            layout: 'anchor',
            defaults: {
                anchor: '100%'
            },
            items: me.createDetailsFormRows(105, 5)
        });

        return me.detailsContainer;
    },

    /**
     * Creates all details form rows containing a label and at least one input field.
     *
     * @param labelWidth The width for all labels in this panel.
     * @param columnPadding The padding between two columns.
     * @return An array containing the created rows.
     */
    createDetailsFormRows: function(labelWidth, columnPadding) {
        var me = this;

        /**
         * Create fields section
         * @type array
         */
        me.salutationRowItems = [
            {
                xtype: 'combobox',
                flex: 2,
                name: 'salutation',
                valueField: 'text',
                displayField: 'snippet',
                queryMode: 'local',
                mode: 'local',
                helpText: me.snippets.details.labels.salutation.help,
                editable: false,
                allowBlank: false,
                store: Ext.create('Ext.data.SimpleStore', {
                    fields: [
                        'text',
                        'snippet'
                    ],
                    data: me.salutationData
                })
            },
            Ext.create('Ext.form.field.Display', {
                width: 100,
                name: '&nbsp;'
            })
        ];

        if (!me.isReturn && me.record) {
            me.salutationRowItems.push(
                Ext.create('Ext.form.field.Checkbox', {
                    name: 'saveInOrder',
                    fieldLabel: me.snippets.details.labels.saveInOrder,
                    labelStyle: 'margin-top: 0px',
                    helpText: me.snippets.tooltips.saveInOrderHelp,
                    labelWidth: 140,
                    flex: 3,
                    uncheckedValue: false,
                    inputValue: true
                })
            );
        }

        me.streetName = Ext.create('Ext.form.field.Text', {
            flex: 6,
            name: 'street',
            allowBlank: false,
            maxLength: me.maxLength.streetName,
            labelConfirmPanel: me,
            validator: me.streetValidator.bind(this),
        });

        me.streetNumber = Ext.create('Ext.form.field.Text', {
            flex: 1,
            name: 'streetNumber',
            allowBlank: false,
            maxLength: me.maxLength.streetNumber,
            labelConfirmPanel: me,
            validator: me.streetValidator.bind(this),
        });

        me.streetNumberBase = Ext.create('Ext.form.field.Text', {
            flex: 1,
            name: 'streetNumberBase',
            allowBlank: false,
            maxLength: me.maxLength.streetNumber,
            labelConfirmPanel: me,
            disabled: true,
            hidden: true,
        });

        me.streetNumberExtension = Ext.create('Ext.form.field.Text', {
            flex: 1,
            name: 'streetNumberExtension',
            allowBlank: true,
            maxLength: me.maxLength.streetNumber,
            labelConfirmPanel: me,
            disabled: true,
            hidden: true,
        });

        me.additionalAddressLine = Ext.create('Ext.form.field.Text', {
            flex: 1799,
            name: 'additionalAddressLine',
            allowBlank: true,
            maxLength: me.maxLength.additionalAddressLine
        });

        me.statesStore = Ext.create('Shopware.store.CountryState');

        me.state = Ext.create('Ext.form.field.ComboBox', {
            flex: 1280,
            name: 'state',
            valueField: 'id',
            displayField: 'name',
            queryMode: 'local',
            mode: 'local',
            required: false,
            editable: false,
            allowBlank: true,
            emptyText: '-',
            store: me.statesStore,
            listeners: {
                change: me.stateChanged,
                scope: me
            }
        });

        me.country = Ext.create('Ext.form.field.ComboBox', {
            flex: 5,
            name: 'country',
            valueField: 'id',
            displayField: 'name',
            queryMode: 'local',
            mode: 'local',
            required: true,
            editable: false,
            allowBlank: false,
            store: me.countriesStore,
            listeners: {
                change: me.countryChanged,
                scope: me
            }
        });

        /**
         * Apply logic from store section
         */
        me.orderConfigData && me.orderConfigData.load({
            scope: me,
            params: {
                shopId: me.record ? me.record.get('shopId') : null
            },
            callback: me.applyConfigDataConstraints
        });

        me.additionalAddressLineRow = me.createFormRow({
            padding: columnPadding,
            label: {
                width: labelWidth,
                text: me.snippets.details.labels.additionalAddressLine
            },
            items: [
                me.additionalAddressLine,
                me.state
            ]
        });

        /**
         * Add Ext Js fields to Row section
         */
        return [
            me.createFormRow({
                rowCls: 'confirm-panel-row-salutation',
                label: {
                    width: labelWidth,
                    text: me.snippets.details.labels.salutation.label
                },
                items: me.salutationRowItems
            }),
            me.createFormRow({
                rowCls: 'confirm-panel-row-name',
                padding: columnPadding,
                label: {
                    width: labelWidth,
                    text: me.snippets.details.labels.name
                },
                items: [{
                    xtype: 'textfield',
                    flex: 1,
                    name: 'firstName',
                    allowBlank: false,
                    maxLength: me.maxLength.firstName,
                    labelConfirmPanel: me,
                    validator: me.nameValidator.bind(this),
                }, {
                    xtype: 'textfield',
                    flex: 1,
                    name: 'lastName',
                    allowBlank: false,
                    maxLength: me.maxLength.lastName,
                    labelConfirmPanel: me,
                    validator: me.nameValidator.bind(this),
                }
                ]
            }),
            me.createFormRow({
                rowCls: 'confirm-panel-row-company',
                padding: columnPadding,
                label: {
                    width: labelWidth,
                    text: me.snippets.details.labels.companyAndDepartment,
                    labelStyle: 'margin-top: 0px'
                },
                items: [{
                    xtype: 'textfield',
                    flex: 1,
                    name: 'company',
                    maxLength: me.maxLength.companyName
                }, {
                    xtype: 'textfield',
                    flex: 1,
                    name: 'department',
                    maxLength: me.maxLength.companyDepartment
                }
                ]
            }),
            me.createFormRow({
                rowCls: 'confirm-panel-row-street',
                padding: columnPadding,
                label: {
                    width: labelWidth,
                    text: me.snippets.details.labels.streetAndNumber,
                    labelStyle: 'margin-top: 0px'
                },
                items: [
                    me.streetName,
                    me.streetNumber,
                    me.streetNumberBase,
                    me.streetNumberExtension
                ]
            }),
            me.additionalAddressLineRow,
            me.createFormRow({
                rowCls: 'confirm-panel-row-city',
                padding: columnPadding,
                label: {
                    width: labelWidth,
                    text: me.snippets.details.labels.zipCityAndCountry
                },
                items: [{
                    xtype: 'textfield',
                    flex: 2,
                    name: 'zipCode',
                    allowBlank: false,
                    maxLength: me.maxLength.zip
                }, {
                    xtype: 'textfield',
                    flex: 5,
                    name: 'city',
                    allowBlank: false,
                    maxLength: me.maxLength.city
                }, me.country
                ]
            }),
            me.createFormRow({
                rowCls: 'confirm-panel-row-phone',
                padding: columnPadding,
                label: {
                    width: labelWidth,
                    text: me.snippets.details.labels.phone
                },
                items: me.getPhoneRowItems()
            })
        ];
    },

    /**
     * Get the phone row items, used for easy overrides
     *
     * @param columnPadding
     */
    getPhoneRowItems: function(columnPadding) {
        var me = this;
        return [
            {
                xtype: 'textfield',
                id: 'phoneField',
                flex: 1,
                name: 'phone',
                allowBlank: true,
                maxLength: me.maxLength.phoneNumber
            },
            Ext.create('Ext.form.field.Display', {
                width: columnPadding,
                name: '&nbsp;'
            }),
            {
                xtype: 'textfield',
                id: 'emailField',
                flex: 2,
                name: 'email',
                allowBlank: true,
                fieldLabel: me.snippets.details.labels.email,
                labelWidth: 40,
                maxLength: me.maxLength.email
            }
        ];
    },

    /**
     * Apply data from config store to the View
     * Example disable Salutation
     *
     * @param records
     * @param operation
     * @param success
     */
    applyConfigDataConstraints: function(records, operation, success) {
        var me = this;

        if (success && records) {
            for (var i = 0, length = records.length; i<length; i++) {
                if (records[i].get('isSalutationRequired') !== undefined) {
                    var form = me.getForm();
                    if (form && form.findField('salutation')) {
                        form.findField('salutation').setDisabled(!records[i].get('isSalutationRequired'));
                    } else {
                        me.salutationRowItems[0].disabled = !records[i].get('isSalutationRequired');
                    }
                    break;
                }
            }
        }
    },

    /**
     * Create the form panel containing the packaging details.
     *
     * @return The created panel.
     */
    createPackagingContainer: function() {
        var me = this;

        me.packagingContainer = Ext.create('Ext.form.Panel', {
            cls: 'confirm-panel-packaging',
            title: me.displayPackagingDimensionFields ? me.snippets.packagingDetails.title : me.snippets.packagingDetails.titleWithoutDimensions,
            bodyPadding: 5,
            margin: '5 0 0 0',
            layout: 'anchor',
            defaults: {
                anchor: '100%'
            },
            items: me.createPackagingFormRows(me.displayPackagingDimensionFields ? 80 : 105, 10)
        });

        return me.packagingContainer;
    },

    /**
     * Creates checkbox for Saturday delivery option
     *
     * To Override example:
     *  var checkBox = this.callParent(arguments);
     *  checkBox.someProperty = ...;
     *  return checkbox;
     *
     * @returns checkbox
     */
    createSaturdayDeliveryCheckBox: function () {
        var me = this;

        var properties = {
            name: 'saturdayDelivery',
            fieldLabel: me.snippets.settingsDetails.labels.saturdayDelivery,
            helpText: me.fillSnippet(me.snippets.tooltips.saturdayDeliveryHelp),
            required: false,
            labelWidth: 110,
            checked: false,
            inputValue: true,
            uncheckedValue: false,
            listeners: {
                change: me.onIsSaturdayDeliveryChecked,
                scope: me
            }
        };

        return Ext.create('Ext.form.field.Checkbox', properties);
    },

    /**
     * Event for Saturday delivery option checkbox
     *
     * @param checkbox
     * @param newValue
     * @param oldValue
     * @param eOpts
     */
    onIsSaturdayDeliveryChecked: function (checkbox, newValue, oldValue, eOpts) {
        // Every adapter can override this
    },

    /**
     * Creates all packaging detail form rows containing a label and at least one input field.
     *
     * @param labelWidth The width for all labels in this panel.
     * @param columnPadding
     * @return An array containing the created rows.
     */
    createPackagingFormRows: function(labelWidth, columnPadding) {
        var me = this;

        // Determine whether the package dimensions are optional
        var opt = me.fieldConstraints ? !me.fieldConstraints.packageDimensionsRequired : true;

        // Create an icon element indicating whether all items of this order have a defined weight or not
        me.weightIcon = Ext.create('Ext.menu.Item', {
            width: 25
        });

        var rows = [];

        if (me.displayPackagingDimensionFields) {
            rows.push(me.createFormRow({
                rowCls: 'confirm-panel-row-packaging-details',
                label: {
                    width: labelWidth,
                    text: me.snippets.packagingDetails.labels.length
                },
                items: [
                    {
                        xtype: 'numberfield',
                        flex: 1,
                        name: 'packagingLength',
                        allowBlank: opt,
                        minValue: 0,
                        allowDecimals: false,
                        maxLength: me.maxLength.length,
                        group: 'packagingDimensions',
                        validator: me.groupValidator
                    },
                    { xtype: 'displayfield', width: columnPadding, name: '&nbsp;' },
                    {
                        xtype: 'numberfield',
                        flex: 2,
                        name: 'packagingWidth',
                        allowBlank: opt,
                        fieldLabel: me.snippets.packagingDetails.labels.width,
                        labelWidth: labelWidth,
                        minValue: 0,
                        allowDecimals: false,
                        maxLength: me.maxLength.width,
                        group: 'packagingDimensions',
                        validator: me.groupValidator
                    },
                    { xtype: 'displayfield', width: columnPadding, name: '&nbsp;' },
                    {
                        xtype: 'numberfield',
                        flex: 2,
                        name: 'packagingHeight',
                        allowBlank: opt,
                        fieldLabel: me.snippets.packagingDetails.labels.height,
                        labelWidth: labelWidth,
                        minValue: 0,
                        allowDecimals: false,
                        maxLength: me.maxLength.length,
                        group: 'packagingDimensions',
                        validator: me.groupValidator
                    }
                ]
            }));
        }

        rows.push(me.createFormRow({
            rowCls: 'confirm-panel-row-weight',
            padding: columnPadding,
            label: {
                width: labelWidth,
                text: me.snippets.packagingDetails.labels.weight
            },
            items: [
                {
                    xtype: 'x-custom-field-weight',
                    width: 100,
                    maxWidth: 100,
                    name: 'weight',
                    allowBlank: false,
                    defaultSubmitValue: 0,
                    maxLength: me.maxLength.weight,
                    /**
                     * Override the default validator method to check if the value is set and a parsable float.
                     *
                     * @return True, if the value is not empty and a parsable float. Otherwise false.
                     */
                    validator: function(value) {
                        if (!isNaN(parseFloat(value.replace(',', '.')))) {
                            return true;
                        }

                        return this.callParent(arguments);
                    },
                    listeners: {
                        change: {
                            fn: me.weightFieldChanged,
                            scope: me
                        }
                    }
                },
                me.weightIcon,
                Ext.create('Ext.form.field.Display', {
                    name: '&nbsp;',
                    flex: 1
                })
            ]
        }));

        return rows;
    },

    /**
     * Create the form panel containing the settings details.
     *
     * @return The created panel.
     */
    createSettingsDetails: function() {
        var me = this;

        me.productComboBox = Ext.create('Ext.form.field.ComboBox', {
            flex: 1,
            name: 'product',
            valueField: 'id',
            displayField: 'name',
            queryMode: 'local',
            mode: 'local',
            required: true,
            editable: false,
            allowBlank: false,
            store: me.productStore,
            listeners: {
                change: me.productChanged,
                scope: me
            }
        });

        me.saturdayDeliveryCheckBox = me.createSaturdayDeliveryCheckBox();

        // Create icon with tooltip shown when there is no product mapping
        me.productIcon = Ext.create('Ext.menu.Item', {
            width: 25,
            iconCls: 'c-sprite-exclamation',
            tooltip: me.fillSnippet(me.snippets.tooltips.productMappingMissing),
            hidden: true
        });

        me.numberOfLabels = Ext.create('Ext.form.field.Number', {
            name: 'numberOfLabels',
            width: 100,
            maxWidth: 100,
            value: 1,
            minValue: 1,
            listeners: {
                change: me.numberOfLabelsFieldChanged,
                scope: me
            }
        });

        // Create icon with tooltip for number of labels
        me.numberOfLabelsIcon = Ext.create('Ext.menu.Item', {
            width: 25,
            iconCls: 'c-sprite-exclamation',
            tooltip: me.snippets.tooltips.numberOfLabelsWeightWarning,
            hidden: true
        });

        me.createExportDocument = Ext.create('Ext.form.field.Checkbox', {
            xtype: 'checkbox',
            name: 'createExportDocument',
            helpText: me.snippets.tooltips.createExportDocumentHelp,
            fieldLabel: me.snippets.settingsDetails.labels.createExportDocument,
            labelWidth: 150,
            required: false,
            checked: false,
            uncheckedValue: false,
            inputValue: true,
            listeners: {
                change: me.createExportDocumentChanged,
                scope: me
            }
        });

        me.cashOnDelivery = Ext.create('Ext.form.field.Checkbox', {
            xtype: 'checkbox',
            name: 'cashOnDelivery',
            checked: false,
            uncheckedValue: false,
            inputValue: true,
            helpText: me.fillSnippet(me.snippets.tooltips.cashOnDeliveryHelp),
            fieldLabel: me.snippets.settingsDetails.labels.cashOnDelivery,
            labelWidth: 69,
            listeners: {
                change: me.cashOnDeliveryChanged,
                scope: me
            }
        });

        me.settingsContainer = Ext.create('Ext.form.Panel', {
            cls: 'confirm-panel-label-type',
            title: me.snippets.settingsDetails.title,
            bodyPadding: 5,
            margin: '5 0 0 0',
            layout: 'anchor',
            defaults: {
                anchor: '100%'
            },
            items: me.createSettingsFormRows(105, 10)
        });

        return me.settingsContainer;
    },

    /**
     * Creates a container holding a field label followed by on or multiple
     * input fields, all in the same row.
     *
     * @param values A object containing the data of the label and fields to create.
     * @return The created container.
     */
    createFormRow: function(values) {
        var cols = [];
        var label = values.label;
        if (label !== undefined) {
            // Add label as first column
            cols.push(
                Ext.create('Ext.form.field.Display', {
                    width: label.width,
                    fieldLabel: label.text,
                    labelStyle: label.labelStyle ? label.labelStyle : '',
                    submitValue: false
                })
            );
        }

        var items = values.items;
        var padding = values.padding;

        // Add items
        for (var i = 0; i < items.length; i++) {
            cols.push(items[i]);

            if (padding !== undefined && i < (items.length - 1)) {
                // Add padding box
                cols.push(
                    Ext.create('Ext.form.field.Display', {
                        width: padding,
                        name: '&nbsp;'
                    })
                );
            }
        }

        return Ext.create('Ext.container.Container', {
            layout: 'hbox',
            align: 'stretch',
            margin: '5 0',
            cls: values.rowCls,
            hidden: ((values.hidden !== undefined) ? values.hidden : false),
            disabled: ((values.disabled !== undefined) ? values.disabled : false),
            items: cols
        });
    },

    /**
     * Create the form panel containing the settings details for the return Label.
     * NOTE: in this case only the product label with combo box has been added,
     *       every adapter should override and change if he needs additional fields
     *
     * @returns  Ext.Form.Panel
     */
    createReturnLabelSettingsDetails: function () {
        var me = this;

        me.productComboBox = Ext.create('Ext.form.field.ComboBox', {
            flex: 1,
            name: 'product',
            valueField: 'id',
            displayField: 'name',
            queryMode: 'local',
            mode: 'local',
            required: true,
            editable: false,
            allowBlank: false,
            store: me.productStore,
            listeners: {
                change: me.productChanged,
                scope: me
            }
        });

        // Create icon with tooltip shown when there is no product mapping
        me.productIcon = Ext.create('Ext.menu.Item', {
            width: 25,
            iconCls: 'c-sprite-exclamation',
            tooltip: me.fillSnippet(me.snippets.tooltips.productMappingMissing),
            hidden: true
        });

        me.settingsContainer = Ext.create('Ext.form.Panel', {
            cls: 'confirm-panel-label-type',
            title: me.customSnippets.settingsDetails.labels.product,
            bodyPadding: 5,
            margin: '5 0 0 0',
            layout: 'anchor',
            defaults: {
                anchor: '100%'
            },
            items: me.createProductLabelFormRows(105, 10)
        });

        return me.settingsContainer;
    },

    /**
     * Create the form panel containing the weight field for the Return Label.
     * NOTE: 'displayPackagingDimensionFields' is used to set the visibility for the
     *        Package dimensions, we override it here to always be false for the 'returnLabel'
     * NOTE: This feature is mainly used for the 'returnLabel',
     *       that's why it is a sepearate function that calls the Packaging container
     *       if we need to add additional setup For 'returnLabel' we can add it here
     *       and it is seperate from the PackagingContainer logic used by 'createLabel'
     */
    createWeightFieldForReturnLabelContainer: function() {
        var me = this;
        me.displayPackagingDimensionFields = false;

        return me.createPackagingContainer();
    },

    /**
     * Creates a product label with combo box
     *
     * @param labelWidth The width for all labels in this panel.
     * @param columnPadding THe padding between the columns
     * @return An array containing the created rows.
     */
    createProductLabelFormRows: function(labelWidth, columnPadding) {
        var me = this;

        return [
            me.createFormRow({
                rowCls: 'confirm-panel-row-product',
                padding: columnPadding,
                label: {
                    width: labelWidth,
                    text: me.customSnippets.settingsDetails.labels.product
                },
                items: [
                    me.productComboBox,
                    me.productIcon
                ]
            })
        ];
    },

    /**
     * Creates a bottom-aligned toolbar containing the 'cancel' and 'confirm' buttons.
     *
     * @return The created toolbar.
     */
    createButtonsContainer: function() {
        var me = this;

        return Ext.create('Ext.toolbar.Toolbar', {
            dock: 'bottom',
            ui: 'footer',
            border: false,
            shadow: false,
            padding: '10 0 5 0',
            style: {
                'background-color': 'transparent',
                'box-shadow': 'none',
                '-moz-box-shadow': 'none',
                '-webkit-box-shadow': 'none',
                '-o-box-shadow': 'none'
            },
            items: [
                { xtype: 'tbfill' },
                Ext.create('Ext.button.Button', {
                    cls: 'secondary',
                    text: me.snippets.buttons.cancel,
                    handler: function() {
                        var confirmWindow = me.up('order-viison-shipping-common-label-confirm-window');
                        me.fireEvent('destroyLabelConfirmWindow', confirmWindow);
                    }
                }),
                Ext.create('Ext.button.Button', {
                    cls: 'primary',
                    text: me.snippets.buttons.confirm,
                    handler: me.confirmButtonClicked,
                    scope: me
                })
            ]
        });
    },

    /**
     * Sets the record values to the corresponding input fields and updates the icon
     * indicating whether some items of the order have no defined weight.
     */
    setValues: function() {
        var me = this;

        if (!me.record) {
            return;
        }
        var record = me.record;

        // Get the weight and update the icon next to the weight field
        var weight = (record[me.dispatchServiceProviderPrefix].calculatedShipmentWeight) ? record[me.dispatchServiceProviderPrefix].calculatedShipmentWeight.weight : null;
        me.updateWeightIcon();

        var shippingRecord = record.getShipping().first();
        var customerRecord = record.getCustomer().first();

        me.detailsContainer.getForm().setValues({
            salutation: shippingRecord.get('salutation'),
            firstName: shippingRecord.get('firstName'),
            lastName: shippingRecord.get('lastName'),
            street: record[me.dispatchServiceProviderPrefix].splittedAddress.streetName,
            streetNumber: record[me.dispatchServiceProviderPrefix].splittedAddress.houseNumber,
            streetNumberBase: record[me.dispatchServiceProviderPrefix].splittedAddress.houseNumberParts.base,
            streetNumberExtension: record[me.dispatchServiceProviderPrefix].splittedAddress.houseNumberParts.extension,
            additionalAddressLine: record[me.dispatchServiceProviderPrefix].splittedAddress.additionalAddressLine,
            zipCode: shippingRecord.get('zipCode'),
            city: shippingRecord.get('city'),
            state: shippingRecord.get('stateId'),
            country: shippingRecord.get('countryId'),
            company: shippingRecord.get('company'),
            department: shippingRecord.get('department'),
            phone: shippingRecord.get('phone'),
            email: customerRecord ? customerRecord.get('email') : '',
        });

        // Prevent state combobox from displaying an id if the state id is incorrect / does not fit the country
        if (me.statesStore.getCount() > 0 && !me.statesStore.getById(me.state.getValue())) {
            me.state.setValue(null);
        }

        if (me.packagingContainer) {
            me.packagingContainer.getForm().setValues({
                packagingLength: record[me.dispatchServiceProviderPrefix].defaultPackageLength,
                packagingHeight: record[me.dispatchServiceProviderPrefix].defaultPackageHeight,
                weight: weight,
                packagingWidth: record[me.dispatchServiceProviderPrefix].defaultPackageWidth
            });
        }

        if (me.settingsContainer) {
            me.settingsContainer.getForm().setValues({
                product: record[me.dispatchServiceProviderPrefix].product,
                createExportDocument: record[me.dispatchServiceProviderPrefix].exportDocumentRequired,
                cashOnDelivery: me.record[me.dispatchServiceProviderPrefix].isCashOnDelivery
            });
        }

        if (me.orderAmountInformation) {
            me.orderAmountInformation.getForm().setValues({
                amount: record.get('invoiceAmount'),
                currency: record.get('currency'),
                insuranceAmount: record.get('invoiceAmount'),
                insuranceCurrency: record.get('currency')
            });

        }

        me.updateProductIcon();
    },

    /**
     * Updates view constraints like the 'allowBlank' config of input fields.
     * That is, the record is checked for potential constraints, which are then applied.
     */
    updateConstraints: function() {
        var me = this;

        if (me.record) {
            me.fieldConstraints = me.record[me.dispatchServiceProviderPrefix].fieldConstraints;
        }

        if (!me.fieldConstraints || !me.packagingContainer) {
            return;
        }
        // Get all items of the packaging container
        var items = me.packagingContainer.items.items[0].items.items;
        for (var i = 0; i < items.length; i++) {
            // Update the allowBlank config for all 'packaging...' fields
            if (items[i].name && items[i].name.indexOf('packaging') === 0) {
                items[i].allowBlank = !me.fieldConstraints.packageDimensionsRequired
            }
        }
    },

    /**
     * Firstly checks if the weight has been precalculated. This is necessary since the request
     * for the calculated weight is async and sometimes finished after this panel was rendered.
     * Finally the information provided by that calculation
     * is used to update the icon and its tooltip next to the weight field.
     */
    updateWeightIcon: function() {
        var me = this;

        // if this label confirm panel does not have a weight field, we have nothing to do
        if (!me.weightIcon) {
            return;
        }

        if (me.record && me.record[me.dispatchServiceProviderPrefix].calculatedShipmentWeight) {
            // Select icon, make it visible and update the tooltip
            var icon = (me.record[me.dispatchServiceProviderPrefix].calculatedShipmentWeight.complete === true) ? 'c-sprite-tick' : 'c-sprite-exclamation';
            var tooltip = (me.record[me.dispatchServiceProviderPrefix].calculatedShipmentWeight.complete === true) ? me.snippets.tooltips.itemWeightsComplete : me.snippets.tooltips.itemWeightsIncomplete;
            me.weightIcon.setIconCls(icon);
            me.weightIcon.setVisible(true);
            me.weightIcon.setTooltip(tooltip);
        }
        if (!me.record || !me.record[me.dispatchServiceProviderPrefix].calculatedShipmentWeight || me.record[me.dispatchServiceProviderPrefix].calculatedShipmentWeight.isDefault) {
            // Weight not defined or is default value
            // Hide icon and remove tooltip
            me.weightIcon.setVisible(false);
            me.weightIcon.setTooltip('');
        }
    },

    /**
     * Checks if a default product mapping for the dispatch type of this order exists
     * and displays a warning sign with tooltip if no mapping exists
     */
    updateProductIcon: function() {
        var me = this;

        // if this label confirm window does not have a product combobox with a product icon, we have nothing to do
        if (!me.productIcon) {
            return;
        }

        var haveDefaultProductMapping = (me.record && me.record[me.dispatchServiceProviderPrefix].product != null);
        me.productIcon.setVisible(!haveDefaultProductMapping);
    },

    /**
     * Checks if the new value of the weight field is still equal to the value set in the record.
     * If it has changed, an icon and a tooltip will be displayed informing the user about
     * the used policy for calculating the weights of the items contained in the order.
     *
     * @param field The field firing the 'change' event.
     * @param newValue The new value of the changed field.
     * @param oldValue The old value of the changed field.
     */
    weightFieldChanged: function(field, newValue, oldValue) {
        var me = this;

        if (!me.record || !me.record[me.dispatchServiceProviderPrefix].calculatedShipmentWeight.weight || me.record[me.dispatchServiceProviderPrefix].calculatedShipmentWeight.isDefault || newValue == oldValue) {
            return;
        }
        if (field.getSubmitValue() != me.record[me.dispatchServiceProviderPrefix].calculatedShipmentWeight.weight) {
            me.weightIcon.setIconCls('c-sprite-exclamation');
            me.weightIcon.setVisible(true);
            me.weightIcon.setTooltip(me.snippets.tooltips.weightManuallyChanged);
        } else {
            me.updateWeightIcon();
        }
    },

    /**
     * Checks if the new value of the number of labels field. If it's greater than 1,
     * a label will be displayed next to the field informing the user about the fact, that
     * each label will use the same weight displayed in the corresponding field.
     *
     * @param field The field firing the 'change' event.
     * @param newValue The new value of the changed field.
     */
    numberOfLabelsFieldChanged: function(field, newValue) {
        if (newValue > 1) {
            this.numberOfLabelsIcon.setVisible(true);
        } else {
            this.numberOfLabelsIcon.setVisible(false);
        }
    },

    /**
     * Update field constraints when the product was changed using the combobox.
     *
     * @param field The field firing the 'change' event.
     * @param newValue The new value of the changed field.
     */
    productChanged: function(field, newValue) {
        var newProduct = this.productStore.findRecord('id', newValue, false, false, false, true);
        if (newProduct) {
            if (this.record) {
                var fieldConstraints = this.record[this.dispatchServiceProviderPrefix].fieldConstraints;
                fieldConstraints.packageDimensionsRequired = newProduct.get('packageDimensionsRequired');
            }
        } else {
            // Reset product field
            field.setRawValue('');
            field.setValue('');
        }
        this.updateConstraints();
    },

    /**
     * Update field constraints when the country was changed using the combobox.
     *
     * @param field The field firing the 'change' event.
     * @param newValue The new value of the changed field.
     */
    countryChanged: function(field, newValue, oldValue) {
        var me = this;

        me.statesStore.getProxy().extraParams = {
            countryId: newValue,
            previousComboBoxValue: oldValue,
            countryField: field
        };
        me.statesStore.load({
            scope: me,
            callback: me.onStateStoreLoad
        });
    },

    /**
     * Load callback for state store
     * @param records
     * @returns boolean
     */
    onStateStoreLoad: function (records) {
        var me = this,
            newValue =  me.statesStore.proxy.extraParams.countryId,
            oldValue = me.statesStore.proxy.extraParams.previousComboBoxValue,
            field = me.statesStore.proxy.extraParams.field;

        if (!records.length) {
            me.state.setValue('');
            me.state.hide();
            me.additionalAddressLineRow.down('displayfield').setFieldLabel(me.snippets.details.labels.additionalAddressLineOnly);
            return true;
        }

        // Add 'none' state
        me.statesStore.insert(0, {
            id: null,
            name: '-'
        });

        if (me.state && oldValue !== undefined && newValue !== oldValue) {
            me.state.setValue('');
        }

        me.additionalAddressLineRow.down('displayfield').setFieldLabel(me.snippets.details.labels.additionalAddressLine);

        me.state.show();
    },

    /**
     * Update field constraints when the state was changed using the combobox. Left empty on purpose for
     * easy extensibility in dispatch service provider plugins.
     *
     * @param field The field firing the 'change' event.
     * @param newValue The new value of the changed field.
     */
    stateChanged: function(field, newValue) {

    },

    /**
     * Validator function that verifies if the length of first and last name together (with a space in between)
     * is smaller or equal to the maximum length given in panel.maxLength.name.
     *
     * @param value
     * @return bool|string True in case of success otherwise an error message string that is displayed in the tooltip.
     */
    nameValidator: function(value) {
        return this.validateFields(
            'name',
            [
                this.detailsContainer.down('[name=firstName]'),
                this.detailsContainer.down('[name=lastName]'),
            ],
            'nameValidationFailed'
        );
    },

    /**
     * Validator function that verifies if the length of street and house number together (with a space in between)
     * is smaller or equal to the maximum length given in panel.maxLength.street.
     *
     * @param value
     * @return bool|string True in case of success otherwise an error message string that is displayed in the tooltip.
     */
    streetValidator: function(value) {
        return this.validateFields(
            'street',
            [
                this.streetName,
                this.streetNumber,
            ],
            'streetValidationFailed'
        );
    },

    /**
     * Function that verifies if the length of the passed fields together (with a space in between)
     * is smaller or equal to the maximum length given via the maxLength constraint.
     *
     * @param { string } rowName The name of the row to use.
     * @param { Ext.form.field.Base[] } fields Array of fields to use to check the max length constraint.
     * @param { string } snippetName Name of the snippet to use.
     * @return { boolean|string } True in case of success otherwise an error message string that is displayed in the tooltip.
     */
    validateFields: function(rowName, fields, snippetName) {
        if (!this.maxLength[rowName]) {
            return true;
        }

        var joinedFieldLength = fields.map(function (field) {
                return field.getValue();
            }).join(' ').length;

        if (joinedFieldLength <= this.maxLength[rowName]) {
            fields.map(function (field) {
                return field.clearInvalid();
            });

            return true;
        } else {
            var errorMessage = Ext.String.format(this.snippets[snippetName], this.maxLength[rowName]);
            fields.map(function (field) {
                return field.markInvalid(errorMessage);
            });

            return errorMessage;
        }
    },

    /**
     * Called when the confirm button was clicked.
     *
     * @param button The button that was clicked.
     */
    confirmButtonClicked: function(button) {
        this.createLabels();
    },

    /**
     * Initiates the label creation process by gathering the form data from the label confirm window and by passing this information
     * as event parameters.
     *
     * @param extraSettings (optional) Extra settings to be applied additionally to the normal settings made in the confirm window.
     */
    createLabels: function(extraSettings) {
        var me = this;
        var confirmWindow = me.up('order-viison-shipping-common-label-confirm-window');
        var details = me.detailsContainer.getForm().getValues();
        var packagingDetails = me.packagingContainer ? me.packagingContainer.getForm().getValues() : null;
        var settings = me.settingsContainer ? me.settingsContainer.getForm().getValues() : null;
        var extraSettings = me.isReturn ? {} : Ext.apply(me.getExtraSettings(), extraSettings);
        var eventType = me.isReturn ? 'createReturnLabel': 'createShippingLabel';
        me.fireEvent(eventType, me.dispatchServiceProviderTab, me.record, details, packagingDetails, settings, extraSettings, confirmWindow);
    },

    /**
     * Create the form panel containing the order amount information.
     *
     * @return The created panel.
     */
    createOrderAmountInformation: function() {
        var me = this;

        me.orderAmountInformation = Ext.create('Ext.form.Panel', {
            cls: 'confirm-panel-label-type',
            title: me.snippets.orderAmountInformation.title,
            bodyPadding: 5,
            margin: '5 0 0 0',
            layout: 'anchor',
            defaults: {
                anchor: '100%'
            },
            collapsible: true,
            items: me.createOrderAmountInformationFormRows(105, 10)
        });

        return me.orderAmountInformation;
    },

    /**
     * Creates all label type form rows containing a label and at least one input field.
     *
     * @param labelWidth The width for all labels in this panel.
     * @param columnPadding
     * @return An array containing the created rows.
     */
    createOrderAmountInformationFormRows: function(labelWidth, columnPadding) {
        var me = this;

        return [
            me.orderAmountInformationAmountRow = me.createFormRow({
                padding: columnPadding,
                label: {
                    width: labelWidth,
                    text: me.snippets.orderAmountInformation.labels.amount,
                    labelStyle: 'margin-top: 0px'
                },
                items: [
                    {
                        xtype: 'numberfield',
                        decimalPrecision: 2,
                        submitLocaleSeparator: false,
                        name: 'amount',
                        flex: 2,
                        allowBlank: false
                    },
                    {
                        xtype: 'textfield',
                        name: 'currency',
                        fieldLabel: me.snippets.orderAmountInformation.labels.currency,
                        labelWidth: 65,
                        value: 'EUR',
                        flex: 1,
                        allowBlank: false
                    }
                ]
            }),
            me.orderAmountInformationInsuranceRow = me.createFormRow({
                padding: columnPadding,
                hidden: true,
                disabled: true,
                label: {
                    width: labelWidth,
                    text: me.snippets.orderAmountInformation.labels.insurance,
                    labelStyle: 'margin-top: 0px'
                },
                items: [
                    {
                        xtype: 'numberfield',
                        decimalPrecision: 2,
                        submitLocaleSeparator: false,
                        name: 'insuranceAmount',
                        flex: 2,
                        allowBlank: false,
                        disabled: true
                    },
                    {
                        xtype: 'textfield',
                        name: 'insuranceCurrency',
                        fieldLabel: me.snippets.orderAmountInformation.labels.currency,
                        labelWidth: 65,
                        value: 'EUR',
                        flex: 1,
                        allowBlank: false,
                        disabled: true
                    }
                ]
            })
        ];
    },

    /**
     * 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);
    },

    /**
     * Listener function that is applied to the 'change' event of all fields.
     * Makes sure that all fields that belong to a group are validated if one
     * of its fields is validated.
     *
     * @param field
     * @param newValue
     * @param oldValue
     * @param eOpts
     */
    fieldChange: function(field, newValue, oldValue, eOpts) {
        if (field.group) {
            var fields = field.up('form').query('[group="' + field.group + '"]');
            Ext.each(fields, function(otherField) {
                if (otherField.name === field.name) {
                    return;
                }
                otherField.validate();
            });
        }
    },

    /**
     * Returns if a field exists that belongs to the given group that is not blank.
     *
     * @param form The form to which the fields belong.
     * @param group The name of the group.
     * @return boolean
     */
    groupHasNonBlankValues: function(form, group) {
        var me = this;

        var fields = form.query('[group="' + group + '"]');

        var hasValues = false;

        Ext.each(fields, function(field) {
            if (!me.isFieldBlank(field)) {
                hasValues = true;

                // break loop
                return false;
            }
        });

        return hasValues;
    },

    /**
     * Checks if a field is blank.
     *
     * @param field
     * @return bool
     */
    isFieldBlank: function(field) {
        return field.getValue() === null || field.getValue() === '' || (field.emptyText && field.getValue() === field.emptyText);
    },

    /**
     * Validator function that can be applied to fields. It makes sure that either
     * all or none of the fields that belong to the corresponding group are blank.
     * Group associations can be set using the group property of fields.
     * Fields that belong to a group can be marked as optional by setting their
     * property optionalGroupField to true.
     *
     * @param value
     * @return true|string True in case of success otherwise an error message string that is displayed in the tooltip.
     */
    groupValidator: function(value) {
        var field = this;
        var me = field.up('order-viison-shipping-common-label-confirm-panel');

        // If the confirm panel is not part of the DOM yet, we cannot perform the validation, so we skip it
        if (!me) {
            return true;
        }

        var form = field.up('form');

        // if there is a field in this group that is not blank, this field must not be blank either
        var allowBlank = !me.groupHasNonBlankValues(form, field.group, field.shopId);

        if (!me.isFieldBlank(field) || field.optionalGroupField || allowBlank) {
            return true;
        } else {
            return me.snippets.groupValidationFailed;
        }
    },

    /**
     * Called when the 'Create export document' checkbox changes its checked state.
     *
     * @param field The field firing the 'change' event.
     * @param newValue The new value of the changed field.
     */
    createExportDocumentChanged: function(field, newValue) {
        // Nothing to do for the standard label confirm panel. Can be overridden in derived classes
        // to react to this event.
    },

    /**
     * Called when the 'Cash on delivery' checkbox changes its checked state. Update the visibility
     * of the order amount information group.
     *
     * @param field The field firing the 'change' event.
     * @param newValue The new value of the changed field.
     */
    cashOnDeliveryChanged: function(field, newValue) {
        this.updateExtraContainersVisibility();
    },

    updateExtraContainersVisibility: function() {
        var me = this;
        if (me.isReturn) {
            return;
        }
        var cashOnDeliveryChecked = me.cashOnDelivery.getValue();
        me.orderAmountInformation.setVisible(cashOnDeliveryChecked);
        if (cashOnDeliveryChecked) {
            me.orderAmountInformation.enable();
        } else {
            me.orderAmountInformation.disable();
        }
    },

    /**
     * Returns additional containers to be added to the items of the label confirm panel.
     *
     * @return A list of containers.
     */
    createExtraContainers: function() {
        return [
            this.createOrderAmountInformation()
        ];
    },

    /**
     * Rows that are returned by this function are added to the settings container.
     */
    createExtraSettingsFormRows: function() {
        // No extra rows for the standard label confirm panel. Can be overridden in derived classes
        // to add new rows to the settings container.
        return [];
    },

    /**
     * Returns all plugin-specific extra key value pairs that should be sent to the PHP controller when
     * creating a label.
     */
    getExtraSettings: function() {
        return this.orderAmountInformation.getForm().getValues();
    },

    /**
     * ========================================
     *  Section:: Helper methods
     * ========================================
     */

    /**
     * Toggle disable & visibility for all fields.
     *
     * @param array fields
     * @param bool isRule
     */
    toggleHelper: function (fields, isRule) {
        this.toggleDisableOptionInAllFiledsFromPanel(fields, isRule); // Disable: true - disable, false - enable
        this.toggleVisibilityOptionFromArrayInPanel(fields, !isRule); // Visibility: true - show, false - hide
    },

    /**
     * Toggle option for disable for all fields.
     *
     * @param array fields
     * @param bool  isDisabled The toggle value for disable
     */
    toggleDisableOptionInAllFiledsFromPanel: function(fields, isDisabled) {
        if (!fields || !fields.forEach) {
            console.error('[ERROR::ShippingCommon] Fields not found');
            return;
        }

        fields.forEach(function(item) {
            item.setDisabled && item.setDisabled(isDisabled);
        });

        // Clean fileds if they are called from a event, so a memory leak doesn't occur
        fields = null;
    },

    /**
     * Toggle option for visibility for all given fields.
     *
     * @param array fields
     * @param bool  isDisabled The toggle value for disable
     */
    toggleVisibilityOptionFromArrayInPanel: function(fields, isVisible) {
        if (!fields || !fields.forEach) {
            console.error('[ERROR::ShippingCommon] Fields not found');
            return;
        }

        fields.forEach(function(item) {
            item.setVisible && item.setVisible(isVisible);
        });

        // Clean fileds if they are called from a event, so a memory leak doesn't occur
        fields = null;
    },

});
