/*
 *  Copyright 2017 Anyware Services
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
 /**
 * This class provides a widget to select one or more content types.<br>
 * This embeds a drop down list with content types name and content types tree selection through a dialog box.<br>
 */
 Ext.define('Ametys.cms.form.widget.SelectContentTypes', {
    
    extend: 'Ametys.form.AbstractQueryableComboBox',
    
    /**
     * @cfg {Object} buttonConfig The configuration object for the button to open content types tree dialog box.
     */
    
    /**
     * @cfg {String} [buttonText=""] the text of the content types tree button.
     */
    buttonText: '',
    
     /**
     * @cfg {String} buttonIcon The button icon path for the content types tree button.
     */
    buttonIcon: null,
     
    /**
     * @cfg {String} buttonIconCls The CSS class to the content types tree button.
     */
    buttonIconCls:  'ametysicon-squares36',
    
    /**
     * @cfg {String} buttonTooltip The button icon tooltip for the content types tree button.
     */
    buttonTooltip: "{{i18n PLUGIN_CMS_WIDGET_SELECTCONTENTTYPES_TOOLTIP_BUTTON}}",
    
    /**
     * @cfg {String} contentTypesDialogTitle Title of the dialog box to choose content type(s). See {@link Ametys.cms.form.widget.ChooseContentTypes#open}.
     */
    contentTypesDialogTitle: "{{i18n PLUGIN_CMS_WIDGET_SELECTCONTENTTYPES_DIALOG_TITLE}}",
    
     /**
     * @cfg {String} contentTypesDialogIconCls The full icon path for the dialog box to choose content type(s). See {@link Ametys.cms.form.widget.ChooseContentTypes#open}.
     */
    contentTypesDialogIconCls: 'ametysicon-squares36',
    
    /**
     * @cfg {String} chooseContentTypesDialogHint The help message to display on top of dialog box to choose content type(s). See {@link Ametys.cms.form.widget.ChooseContentTypes#open}.
     */
    chooseContentTypesDialogHint: "{{i18n PLUGIN_CMS_WIDGET_SELECTCONTENTTYPES_DIALOG_HINT}}",

    /**
     * @cfg {Object} enumeration The list of available values.
     */
    /**
     * @cfg {Boolean/String} [naturalOrder=false] True to sort drop down list by natural order. By default alphabetical order is applied to the store.
     */
    
    /**
     * @cfg {Object} enumerationConfig The configuration of enumerator :
     * @cfg {Boolean/String} [enumerationConfig.excludePrivate=false] True to exclude private content types. By default excludePrivate is false.
     * @cfg {Boolean/String} [enumerationConfig.excludeReferenceTable=true] True to exclude reference table content types. By default excludeReferenceTable is true.
     * @cfg {Boolean/String} [enumerationConfig.excludeAbstract=false] True to exclude abstract content types. By default excludeAbstract is false.
     * @cfg {Boolean/String} [enumerationConfig.excludeMixin=false] True to exclude mixin content types. By default excludeMixin is false.
     * @cfg {Boolean/String} [enumerationConfig.includeMixinOnly=false] True to only include mixin content types. By default includeMixinOnly content type is false.
     * @cfg {String[]|String} [enumerationConfig.strictContentTypes] The strict content types id separated by comma or in an array
     * @cfg {String[]|String} [enumerationConfig.contentTypes] The parent content types id separated by comma separated by comma or in an array
     */
    
    /**
     * @private
     * @property {Boolean} _excludeReferenceTable If true, reference table will be excluded
     */
    /**
     * @private
     * @property {Boolean} _excludePrivate If true, private content types will be excluded
     */
    /**
     * @private
     * @property {Boolean} _excludeAbstract If true, abstract content types will be excluded
     */
    /**
     * @private
     * @property {Boolean} _excludeMixin If true, mixin content types will be excluded
     */
    /**
     * @private
     * @property {Boolean} _includeMixinOnly If true, only mixin content types will be available
     */
    /**
     * @private
     * @property {String[]} _strictContentTypes If not null nor empty, the widget will be restricted only to theses content types
     */
    /**
     * @private
     * @property {String[]} _contentTypes If not null nor empty, the widget will be restricted only to theses content types and their subtypes
     */
    
    /**
     * @private 
     * @property {Ext.data.Store} _store The store of drop down list.
     */
    
    queryMode: 'local',
    
    initComponent: function()
    {
        var enumerationConfig = Ext.applyIf(this.enumerationConfig || {}, {
            excludeReferenceTable: false,
            excludeMixin: false,
            excludeAbstract: false,
            excludePrivate: false,
            includeMixinOnly: false,
            includeSupertype: false
        });
        
        this.multiple = this.multiple === true || this.multiple == 'true';
        
        this._excludeReferenceTable = enumerationConfig.excludeReferenceTable !== false && enumerationConfig.excludeReferenceTable != 'false';
        this._excludeMixin = enumerationConfig.excludeMixin === true || enumerationConfig.excludeMixin == 'true';
        this._excludeAbstract = enumerationConfig.excludeAbstract === true || enumerationConfig.excludeAbstract == 'true';
        this._excludePrivate = enumerationConfig.excludePrivate === true || enumerationConfig.excludePrivate == 'true';
        this._includeMixinOnly = enumerationConfig.includeMixinOnly === true  || enumerationConfig.includeMixinOnly == 'true';
        this._strictContentTypes = enumerationConfig.strictContentTypes === undefined ? null : Ext.isArray(enumerationConfig.strictContentTypes) ? enumerationConfig.strictContentTypes : enumerationConfig.strictContentTypes.split(',');
        this._contentTypes = enumerationConfig.contentTypes === undefined ? null : Ext.isArray(enumerationConfig.contentTypes) ? enumerationConfig.contentTypes : enumerationConfig.contentTypes.split(',');
        
        this.callParent(arguments);
    },
    
    getItems: function()
    {
        var items = this.callParent(arguments);
        
        if (!this.readOnly)
        {
            var buttonConfig = this.buttonConfig || {};
            Ext.applyIf(buttonConfig, {
                text: this.buttonText,
                icon: this.buttonIcon,
                iconCls: this.buttonIcon ? null : this.buttonIconCls,
                tooltip: this.buttonTooltip,
                handler: this._chooseContentTypes,
                scope: this
            });
            items.push(Ext.create('Ext.button.Button', buttonConfig));
        }
        
        return items;
    },
    
    /**
     * @private
     * Open a dialog box to select content type(s).
     */
    _chooseContentTypes: function()
    {
        var config = {
            title: this.contentTypesDialogTitle,
            iconCls: this.contentTypesDialogIconCls,
            helpMessage: this.chooseContentTypesDialogHint,
            excludeReferenceTable: this._excludeReferenceTable,
            excludeMixin: this._excludeMixin,
            excludeAbstract: this._excludeAbstract,
            excludePrivate: this._excludePrivate,
            includeMixinOnly: this._includeMixinOnly,
            strictContentTypes: this._strictContentTypes,
            contentTypes: this._contentTypes,
            multiple: this.multiple,
            values: Ext.clone(this.getValue()),
            callback: Ext.bind(this._chooseContentTypesCb, this)
        }
        Ametys.cms.form.widget.ChooseContentTypes.open(config);
    },
    
    /**
     * @private
     * Callback function called after selecting content types in a tree.
     * Update the field value.
     * @param {String[]} contentTypeIds The ids of selected content types
     */
    _chooseContentTypesCb: function(contentTypeIds)
    {
        this.setValue(contentTypeIds);
    },
    
    getStore: function()
    {
        if (!this._store)
        {
            if (this.getInitialConfig().enumeration)
            {
                var storeCfg = {
                    fields: [ this.valueField, {name: this.displayField, type: 'string'}],
                    data: this.getInitialConfig().enumeration
                };
                this.queryMode = 'local';
                
                
                this.naturalOrder = Ext.isBoolean(this.naturalOrder) ? this.naturalOrder : this.naturalOrder == 'true';
                if (!this.naturalOrder)
                {
                    storeCfg.sorters = [{property: this.displayField, direction:'ASC'}]; // default order
                }
    
                this._store = Ext.create('Ext.data.ArrayStore', storeCfg);
            }
            else
            {
                this._store = Ext.create('Ext.data.Store', this._getRemoteStoreCfg());
            }
        }
        return this._store;
    },
    
    /**
     * Get the remote store.
     * @return {Ext.data.Store} the remote store.
     */
    _getRemoteStoreCfg: function()
    {
        var cfg = {
            autoLoad: true,
            
            proxy: {
                type: 'ametys',
                role: 'org.ametys.cms.contenttype.ContentTypesTreeComponent',
                methodName: 'getContentTypes',
                reader: {
                    type: 'json',
                    rootProperty: 'children'
                }
            },
            
            listeners: {
                'beforeload': this._onBeforeLoad,
                scope: this
            },
            
            fields: [
                {name: 'id', mapping: 'contentTypeId'},
                {name: 'label', mapping: 'text'}
            ]
        }
        
        var naturalOrder = Ext.isBoolean(this.naturalOrder) ? this.naturalOrder : this.naturalOrder == 'true';
        if (!naturalOrder)
        {
            cfg.sorters = [{property: 'label', direction:'ASC'}]; // default order
        }
        
        return cfg;
    },
    
    /**
     * Function called before loading the store
     * @param {Ext.data.Store} store The store
     * @param {Ext.data.operation.Operation} operation The object that will be passed to the Proxy to load the store
     * @private
     */
    _onBeforeLoad: function(store, operation)
    {
        operation.setParams( Ext.apply(operation.getParams() || {}, {
            includeMixinOnly: this._includeMixinOnly,
            hierarchicalView: false,
            excludeReferenceTable: this._excludeReferenceTable,
            excludeMixin: this._excludeMixin,
            excludeAbstract: this._excludeAbstract,
            excludePrivate: this._excludePrivate,
            excludeMode: 'hide',
            strictContentTypes: this._strictContentTypes,
            contentTypes: this._contentTypes
        }));
    }
    
});