/**
 * This class implements the configurator panel.
 */
Ext.define('Ext.pivot.plugin.configurator.Panel', {
    extend: 'Ext.Panel',
 
    requires: [
        'Ext.pivot.plugin.configurator.Container',
        'Ext.pivot.plugin.configurator.DragZone',
        'Ext.pivot.plugin.configurator.DropZone',
        'Ext.pivot.plugin.configurator.PanelController',
        'Ext.pivot.plugin.configurator.Form',
        'Ext.pivot.plugin.configurator.Settings',
        'Ext.layout.HBox',
        'Ext.layout.VBox',
        'Ext.layout.Card',
        'Ext.TitleBar',
        'Ext.Promise'
    ],
 
    alias: 'widget.pivotconfigpanel',
    controller: 'pivotconfigpanel',
 
    isPivotConfigPanel: true,
 
    cls: Ext.baseCSSPrefix + 'pivot-grid-config-panel',
 
    showAnimation: {
        type: 'slideIn',
        duration: 250,
        easing: 'ease-out',
        direction: 'left'
    },
 
    hideAnimation: {
        type: 'slideOut',
        duration: 250,
        easing: 'ease-in',
        direction: 'right'
    },
 
    panelTitle:             'Configuration',
    /**
     * @cfg {String} panelAllFieldsText Text displayed in the container reserved for all available fields
     * when docked to top or bottom.
     */
    panelAllFieldsText:     'Drop Unused Fields Here',
    /**
     * @cfg {String} panelAllFieldsTitle Text displayed in the container reserved for all available fields
     * when docked to left or right.
     */
    panelAllFieldsTitle:    'All fields',
 
    /**
     * @cfg {String} panelTopFieldsText Text displayed in the container reserved for all top axis fields
     * when docked to top or bottom.
     */
    panelTopFieldsText:     'Drop Column Fields Here',
    /**
     * @cfg {String} panelTopFieldsTitle Text displayed in the container reserved for all top axis fields
     * when docked to left or right.
     */
    panelTopFieldsTitle:    'Column labels',
 
    /**
     * @cfg {String} panelLeftFieldsText Text displayed in the container reserved for all left axis fields
     * when docked to top or bottom.
     */
    panelLeftFieldsText:    'Drop Row Fields Here',
    /**
     * @cfg {String} panelLeftFieldsTitle Text displayed in the container reserved for all left axis fields
     * when docked to left or right.
     */
    panelLeftFieldsTitle:   'Row labels',
 
    /**
     * @cfg {String} panelAggFieldsText Text displayed in the container reserved for all aggregate fields
     * when docked to top or bottom.
     */
    panelAggFieldsText:     'Drop Agg Fields Here',
    /**
     * @cfg {String} panelAggFieldsTitle Text displayed in the container reserved for all aggregate fields
     * when docked to left or right.
     */
    panelAggFieldsTitle:    'Values',
    cancelText:             'Cancel',
    okText:                 'Done',
 
    eventedConfig: {
        pivot:          null,
        fields:         null
    },
 
    listeners: {
        pivotchange: 'onPivotChanged',
        fieldschange: 'onFieldsChanged'
    },
 
    layout: 'card',
 
    initialize: function(){
        this.setup();
        return this.callParent();
    },
 
    /**
     * This function either moves or copies the dragged field from one container to another.
     *
     * @param {Ext.pivot.plugin.configurator.Container} fromContainer
     * @param {Ext.pivot.plugin.configurator.Container} toContainer
     * @param {Ext.data.Model} record
     * @param {String} newPos New index position
     *
     * @private
     */
    dragDropField: function(fromContainer, toContainer, record, newPos){
        var me = this,
            pivot = me.getPivot(),
            field = record.get('field'),
            fromFieldType = fromContainer.getFieldType(),
            toFieldType = toContainer.getFieldType(),
            controller = me.getController(),
            topAxisCt = controller.getTopAxisContainer(),
            leftAxisCt = controller.getLeftAxisContainer(),
            item;
 
        if(pivot.fireEvent('beforemoveconfigfield', this, {
                fromContainer:  fromContainer,
                toContainer:    toContainer,
                field:          field
            }) !== false){
 
            if(fromContainer != toContainer){
 
                if (toFieldType === 'all') {
                    // source is "Row labels"/"Column labels"/"Values" 
                    // destination is "All fields" 
                    // we just remove the field from the source 
                    fromContainer.removeField(record);
                } else if (toFieldType === 'aggregate') {
                    // source is "Row labels"/"Column labels"/"All fields" 
                    // destination is "Values" 
                    // we copy the field to destination 
                    toContainer.addField(field, newPos);
                    if (fromFieldType !== 'all'){
                        // remove the field from the left/top axis 
                        fromContainer.removeField(record);
                    }
                } else {
                    // source is "Row labels"/"Column labels"/"Values"/"All fields" 
                    // destination is "Row labels"/"Column labels" 
                    // first let's check if the field is already in the destination container 
                    item = me.findFieldInContainer(field, toContainer);
 
                    if (item) {
                        // the destination has the field already 
                        return;
                    }
 
                    // See if it was on another axis. 
                    if (toFieldType === 'leftAxis') {
                        item = me.findFieldInContainer(field, topAxisCt);
                        fromContainer = item ? topAxisCt : fromContainer;
                    } else {
                        item = me.findFieldInContainer(field, leftAxisCt);
                        fromContainer = item ? leftAxisCt : fromContainer;
                    }
 
                    // If so, move it here. 
                    if (item) {
                        fromContainer.removeField(item);
                        toContainer.addField(field);
                    } else {
                        if(fromFieldType === 'aggregate'){
                            // we need to remove the dragged field because it was found on one of the axis 
                            fromContainer.removeField(record);
                        }
                        toContainer.addField(field, newPos);
                    }
                }
            }else{
                toContainer.moveField(record, newPos);
            }
        }
 
    },
 
    isAllowed: function (fromContainer, toContainer, record) {
        var allowed = true,
            field = record.get('field'),
            fromFieldType = fromContainer && fromContainer.getFieldType(),
            toFieldType = toContainer && toContainer.getFieldType();
 
        if (fromFieldType === 'aggregate' && (toFieldType === 'leftAxis' || toFieldType === 'topAxis')) {
            allowed = !this.findFieldInContainer(field, toContainer);
        }
        return allowed;
    },
 
    /**
     *
     * @param {Ext.pivot.plugin.configurator.Field} field
     * @param {Ext.pivot.plugin.configurator.Container} container
     * @return {Ext.data.Model}
     *
     * @private
     */
    findFieldInContainer: function(field, container){
        var store = container.getStore(),
            length = store.getCount(),
            i, item;
 
        for(= 0; i < length; i++){
            item = store.getAt(i);
            if(item.get('field').getDataIndex() == field.getDataIndex()){
                return item;
            }
        }
    },
 
    setup: function(){
        var me = this,
            listeners = {
                configchange:       'onConfigChanged',
                toolsbtnpressed:    'showCard',
                removefield:        'onRemoveField'
            };
 
        me.add([{
            itemId: 'main',
            xtype: 'container',
            layout: {
                type: 'hbox',
                align: 'stretch'
            },
 
            defaults: {
                flex: 1
            },
 
            items: [{
                xtype:      'titlebar',
                docked:     'top',
                title:      me.panelTitle,
                titleAlign: 'left',
                items: [{
                    xtype: 'tool',
                    type: 'gear',
                    align: 'right',
                    handler: 'showSettings'
                },{
                    text:   me.cancelText,
                    align:  'right',
                    ui:     'alt',
                    handler:'cancelConfiguration'
                },{
                    text:   me.okText,
                    align:  'right',
                    ui:     'alt',
                    handler:'applyConfiguration',
                    margin: '0 0 0 5'
                }]
            },{
                reference:  'fieldsCt',
                xtype:      'pivotconfigcontainer',
                title:      me.panelAllFieldsTitle,
                emptyText:  me.panelAllFieldsText,
                fieldType:  'all',
                listeners:  listeners
            },{
                xtype: 'container',
                layout: {
                    type: 'vbox',
                    align: 'stretch'
                },
                defaults: {
                    xtype:      'pivotconfigcontainer',
                    flex: 1
                },
                items: [{
                    reference:  'fieldsAggCt',
                    title:      me.panelAggFieldsTitle,
                    emptyText:  me.panelAggFieldsText,
                    fieldType:  'aggregate',
                    listeners:  listeners
                },{
                    reference:  'fieldsLeftCt',
                    title:      me.panelLeftFieldsTitle,
                    emptyText:  me.panelLeftFieldsText,
                    fieldType:  'leftAxis',
                    listeners:  listeners
                },{
                    reference:  'fieldsTopCt',
                    title:      me.panelTopFieldsTitle,
                    emptyText:  me.panelTopFieldsText,
                    fieldType:  'topAxis',
                    listeners:  listeners
                }]
            }]
 
        },{
            itemId: 'field',
            xtype: 'pivotconfigform',
            listeners: {
                close: 'backToMainView',
                beforeapplyconfigfieldsettings: 'onBeforeApplyConfigFieldSettings',
                applyconfigfieldsettings: 'onApplyConfigFieldSettings'
            }
        },{
            itemId: 'settings',
            xtype: 'pivotsettings',
            listeners: {
                close: 'backToMainView',
                beforeapplypivotsettings: 'onBeforeApplyPivotSettings',
                applypivotsettings: 'onApplyPivotSettings'
            }
        }]);
    },
 
    /**
     * Returns the container that stores all unused fields.
     *
     * @returns {Ext.pivot.plugin.configurator.Container}
     */
    getAllFieldsContainer: function(){
        return this.lookup('fieldsCt');
    },
 
    /**
     * Returns the header of the container that stores all unused fields.
     *
     * @return {Ext.panel.Header}
     * @since 6.5.0
     */
    getAllFieldsHeader: function(){
        return this.getAllFieldsContainer().getHeader();
    },
 
    /**
     * Set visibility of the "All fields" header and container
     * @param {Boolean} visible 
     * @since 6.5.0
     */
    setAllFieldsContainerVisible: function(visible){
        this.getAllFieldsContainer().setHidden(!visible);
    },
 
    /**
     * Returns the container that stores all fields configured on the left axis.
     *
     * @returns {Ext.pivot.plugin.configurator.Container}
     */
    getLeftAxisContainer: function(){
        return this.lookup('fieldsLeftCt');
    },
 
    /**
     * Returns the header of the container that stores all fields configured on the left axis.
     *
     * @return {Ext.panel.Header}
     * @since 6.5.0
     */
    getLeftAxisHeader: function(){
        return this.getLeftAxisContainer().getHeader();
    },
 
    /**
     * Set visibility of the "Row labels" header and container
     * @param {Boolean} visible 
     * @since 6.5.0
     */
    setLeftAxisContainerVisible: function(visible){
        this.getLeftAxisContainer().setHidden(!visible);
    },
 
    /**
     * Returns the container that stores all fields configured on the top axis.
     *
     * @returns {Ext.pivot.plugin.configurator.Container}
     */
    getTopAxisContainer: function(){
        return this.lookup('fieldsTopCt');
    },
 
    /**
     * Returns the header of the container that stores all fields configured on the top axis.
     *
     * @return {Ext.panel.Header}
     * @since 6.5.0
     */
    getTopAxisHeader: function(){
        return this.getTopAxisContainer().getHeader();
    },
 
    /**
     * Set visibility of the "Column labels" header and container
     * @param {Boolean} visible 
     * @since 6.5.0
     */
    setTopAxisContainerVisible: function(visible){
        this.getTopAxisContainer().setHidden(!visible);
    },
 
    /**
     * Returns the container that stores all fields configured on the aggregate.
     *
     * @returns {Ext.pivot.plugin.configurator.Container}
     */
    getAggregateContainer: function(){
        return this.lookup('fieldsAggCt');
    },
 
    /**
     * Returns the header of the container that stores all fields configured on the aggregate.
     *
     * @return {Ext.panel.Header}
     * @since 6.5.0
     */
    getAggregateHeader: function(){
        return this.getAggregateContainer().getHeader();
    },
 
    /**
     * Set visibility of the "Values" header and container
     * @param {Boolean} visible 
     * @since 6.5.0
     */
    setAggregateContainerVisible: function(visible){
        this.getAggregateContainer().setHidden(!visible);
    }
 
});