/*
 *  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 entry of a reference table content type.<br>
 * This embeds a drop down list with querying on title of contents and type-ahead support.<br>
 * Advanced search and content creation are disabled.<br>
 * 
 * This widget is registered for fields of type Ametys.form.WidgetManager#TYPE_CONTENT.<br>
 */
Ext.define('Ametys.cms.form.widget.SelectReferenceTableContent', {
    extend: 'Ametys.cms.form.widget.SelectContent',
    
    allowSearch: false,
    allowCreation: false,
    openOnClick: false,
    
    modelId: null,
    /**
     * @cfg {String} [contentType] The content type to allow search on. If not null, the search will be restricted the search to this content type (and its sub-types).
     */
    contentType: null, 
    /**
     * @cfg {Boolean} [allowHierarchicalTreeOpening=true] Set to `false` to not display the button for selecting the content in its potential hierarchy.
     */
    allowHierarchicalTreeOpening: true,
    
    /**
     * @cfg {Object} openTreeButtonConfig The configuration object for the button to open hierarchical tree
     */
    /**
     * @cfg {String} [openTreeButtonText=""] The text of the button for opening the hierarchical tree.
     * Note that if you supply a value for {@link #openTreeButtonConfig}, the openTreeButtonConfig.text
     * value will be used instead if available.
     */
    openTreeButtonText: '',
    
    /**
     * @cfg {String} [openTreeButtonIconCls="ametysicon-squares36"] One or more space separated CSS classes to be applied to the icon of button for opening the hierarchical tree. Only used if {@link #openTreeButtonIcon} is null.
     * Note that if you supply a value for {@link #openTreeButtonConfig}, the openTreeButtonCfg.iconCls
     * value will be used instead if available.
     */
    openTreeButtonIconCls: 'ametysicon-squares36',
    
    /**
     * @cfg {String} [openTreeButtonIcon] The button icon path for the button for opening the hierarchical tree.
     * Note that if you supply a value for {@link #openTreeButtonConfig}, the openTreeButtonCfg.icon
     * value will be used instead if available.
     */
    openTreeButtonIcon: null,
    
    /**
     * @cfg {String} openTreeButtonTooltip The button icon tooltip for the button for opening the hierarchical tree.
     */
    openTreeButtonTooltip: "{{i18n WIDGET_SELECT_REFERENCETABLE_CONTENT_OPENTREEBUTTON_TOOLTIP}}",
    
    /**
     * @cfg {String} buttonAutopostingEnabledIconCls The separated CSS classes to apply to button for autoposting enabled
     */
    buttonAutopostingEnabledIconCls: 'ametysicon-text decorator-ametysicon-check34 referencetable-autoposting referencetable-autoposting-enabled',
    /**
     * @cfg {String} buttonAutopostingDisabledIconCls The separated CSS classes to apply to button for autoposting disabled
     */
    buttonAutopostingDisabledIconCls: 'ametysicon-text decorator-ametysicon-delete30 referencetable-autoposting referencetable-autoposting-disabled',
    
    /**
     * @cfg {String} [searchModelIdForContentsWithSameReferencing="search-ui.referencing-contents-with-same-values"] The id of search model for search on contents referencing widget's same  values
     */
    searchModelIdForContentsWithSameReferencing: 'search-ui.referencing-contents-with-same-values',
    /**
     * @cfg {Boolean} [allowSearchOnContentsWithSameReferencing=false] Set to `true` to display a button to search on contents referencing widget's same  values
     */
    allowSearchOnContentsWithSameReferencing: false,
    /**
     * @cfg {String} searchOnContentsWithSameReferencingButtonIcon The icon path for the button to open search tool on same referencing contents. Only used if {#cfg-allowSearchOnContentsWithSameReferencing} is true
     */
    searchOnContentsWithSameReferencingButtonIcon: null,
    /**
     * @cfg {String} searchOnContentsWithSameReferencingButtonIconCls The separated CSS classes to apply to button for open search tool on same referencing contents. Only used if {#cfg-allowSearchOnContentsWithSameReferencing} is true
     */
    searchOnContentsWithSameReferencingButtonIconCls: 'ametysicon-object-binoculars',
    /**
     * @cfg {String} searchOnContentsWithSameReferencingButtonTooltip The tooltip use for button to open search tool on same referencing contents. Only used if {#cfg-allowSearchOnContentsWithSameReferencing} is true
     */
    searchOnContentsWithSameReferencingButtonTooltip: "{{i18n WIDGET_REFERENCE_TABLE_SEARCH_REFERENCING_CONTENTS_BUTTON_TOOLTIP}}",
    
    /**
     * @cfg {Boolean} [allowToggleAutoposting=false] Set to `true` to allow autoposting during search. 
     */
    allowToggleAutoposting: false,
    
    /**
     * @cfg {Boolean} [activateTopItemAlert=false] Set to 'true' to activate the alert when a item of first level (with children) is selected
     */
    activateTopItemAlert: false,
    
    /**
     * @cfg {Boolean} [topItemAlertTitle] The title of alert when a item of first level (with children) is selected. If empty, the default alert title will be used. Only used if {#cfg-activateTopItemAlert} is true.
     */
    /**
     * @cfg {Boolean} [topItemAlertText] The text of alert when a item of first level (with children) is selected. If empty, the default alert text will be used. Only used if {#cfg-activateTopItemAlert} is true.
     */
    
    /**
     * @property {String} _activeAutoposting Set to 'true' to activate the autoposting.
     * Only used if the create {@link #cfg-allowToggleAutoposting} has need set to true.
     * @protected
     */
    
    constructor: function (config)
    {
    	config.allowToggleAutoposting = config.allowToggleAutoposting === true || config.allowToggleAutoposting == 'true';
    	config.activateTopItemAlert = config.activateTopItemAlert === true || config.activateTopItemAlert == 'true';
        
        if (config.contentInfo && config.contentInfo.contentId)
        {
            config.allowSearchOnContentsWithSameReferencing = config.allowSearchOnContentsWithSameReferencing === true || config.allowSearchOnContentsWithSameReferencing == 'true';
        }
        else
        {
            // Search on contents with same referenced values necessary needs a current content
            config.allowSearchOnContentsWithSameReferencing = false;
        }
        
        config.allowHierarchicalTreeOpening = config.allowHierarchicalTreeOpening !== false && config.allowHierarchicalTreeOpening !== "false";
        
        config.limitToContextLanguage = false;
        
    	this.callParent(arguments);
    },
    
    initComponent: function()
    {
        if (this.modelId == null) // otherwise keep the modelId from config
        {
            this.modelId = "reference-table-search-ui." + this.contentType;
        }
        this.callParent(arguments);
    },
    
    getItems: function()
    {
        var items = this.callParent(arguments);
        
        if (!this.readOnly 
            && this.allowHierarchicalTreeOpening
            && this.contentType != null
            && Ametys.cms.content.ContentTypeDAO.getContentType(this.contentType).getParentMetadataName() != "")
        {
            var openTreeButtonConfig = this.openTreeButtonConfig || {};
            Ext.applyIf(openTreeButtonConfig, {
                itemId: "openTreeButton",
                text: this.openTreeButtonText,
                iconCls: this.openTreeButtonIcon ? null : this.openTreeButtonIconCls,
                icon: this.openTreeButtonIcon,
                tooltip: this.openTreeButtonTooltip,
                handler: this._chooseContentInTree,
                scope: this
            });
            this.openTreeButton = Ext.create('Ext.button.Button', openTreeButtonConfig);
            items.push(this.openTreeButton);
        }
        
        if (this.allowToggleAutoposting)
        {
            this._activeAutoposting = true;
            
            items.push(Ext.create('Ext.button.Button', {
                itemId: 'toggle-autoposting',
                text: '',
                iconCls: this._activeAutoposting ? this.buttonAutopostingEnabledIconCls : this.buttonAutopostingDisabledIconCls,
                tooltip: this._activeAutoposting ? "{{i18n WIDGET_REFERENCE_TABLE_AUTOPOSTING_ENABLED}}" : "{{i18n WIDGET_REFERENCE_TABLE_AUTOPOSTING_DISABLED}}",
                enableToggle: true,
                pressed: this._activeAutoposting,
                toggleHandler: function (btn, state) {
                    this._activeAutoposting = state;
                    
                    if (this._activeAutoposting)
                    {
                        btn.setIconCls(this.buttonAutopostingEnabledIconCls);
                        btn.setTooltip("{{i18n WIDGET_REFERENCE_TABLE_AUTOPOSTING_ENABLED}}")
                    }
                    else
                    {
                        btn.setIconCls(this.buttonAutopostingDisabledIconCls);
                        btn.setTooltip("{{i18n WIDGET_REFERENCE_TABLE_AUTOPOSTING_DISABLED}}");
                    }
                },
                scope: this
            }));
        }
        
        if (this.allowSearchOnContentsWithSameReferencing)
        {
            items.push(Ext.create('Ext.button.Button', {
                itemId: 'search-same-referencing-contents',
                text: '',
                iconCls: this.searchOnContentsWithSameReferencingButtonIcon ? null : this.searchOnContentsWithSameReferencingButtonIconCls,
                tooltip: this.searchOnContentsWithSameReferencingButtonTooltip,
                handler: this.searchOnContentsWithSameReferencing,
                disabled: true,
                scope: this
            }));
            
	        this.combobox.on("change", this._onValueChange, this);
        }
        
        return items;
    },
    
    setValue: function(value)
    {
        if (Ext.isObject(value) && value.value)
        {
            if (this.allowToggleAutoposting)
            {
                this.items.get('toggle-autoposting').toggle(value.autoposting || false);
            }
            value = value.value;
        }
        
        this.callParent([value]);
    },
   
    getValue: function ()
    {
    	var value = this.callParent(arguments);
        
        if (this.allowToggleAutoposting == true)
        {
            if (!Ext.isEmpty(value))
            {
                return {
                   value: value,
                   autoposting: this._activeAutoposting
                };	
            }
        }
        
        return value;
    },
    
    getSubmitValue: function ()
    {
        return this.multiple || (this.allowToggleAutoposting == true || this.allowToggleAutoposting == 'true') ? Ext.encode(this.getValue()) : this.getValue();
    },
    
    /**
     * @private
     * Listener when the value change, to enable/disable the button to see referencing contents.
     * @param {Ext.form.field.Tag} combobox The combobox
     * @param {String|String[]} newValue The new value
     * @param {String|String[]} oldValue The old value
     */
    _onValueChange: function(combobox, newValue, oldValue)
    {
        var searchReferencingBtn = this.down('#search-same-referencing-contents');
        if (searchReferencingBtn)
        {
        	searchReferencingBtn.setDisabled(Ext.isEmpty(newValue));
        }
    },
    
    /**
     * @private
     * Open the dialog box to display the hierarchy of reference tables.
     */
    _chooseContentInTree: function()
    {
    	var ids = this._getIds();
        Ametys.cms.uihelper.ChooseHierarchicalContent.open({
            allowToggleAutoposting: this.allowToggleAutoposting,
            activeAutoposting: this._activeAutoposting,
        	activateTopItemAlert: this.activateTopItemAlert,
            topItemAlertTitle: this.topItemAlertTitle,
            topItemAlertText: this.topItemAlertText,
            leafContentType: this.contentType,
            multiple: this.multiple,
            values: ids,
            callback: Ext.bind(this._chooseContentInTreeCb, this)
        });
    },
    
    /**
     * @private
     * Callback function after some contents have been selected in the helper.
     * Select the contents in the combobox.
     * @param {String[]} contents The ids of the selected contents in the tree
     * @param {Boolean} autoposting 'true' if the autoposting button is activated
     */
    _chooseContentInTreeCb: function(contents, autoposting)
    {
        contents = Ext.Array.from(contents);
    	this.setValue({
            value : (this.multiple ? contents : (contents.length > 0 ? contents[0] : null)),
            autoposting: autoposting
        });
    },
       
    /**
     * @private
     * Get the ids of the values selected
     */
    _getIds: function()
    {
    	var values = this.getValue();
    	var ids = [];
    	
    	if (values)
    	{
    		values = Ext.Array.from(values);
            Ext.Array.each(values, function(v) {
            	if (Ext.isObject(v) && v.value)
            	{
            		ids.push(v.value);
            	}	
            	else
            	{
            		ids.push(v);
            	}
            })
    	}
    	return ids;
    },
    
    /**
     * Open a search tool with the referencing contents.
     */
    searchOnContentsWithSameReferencing: function ()
    {
        if (this.contentInfo && this.contentInfo.contentId)
        {
	        var fieldName = this.getName();
	        var fieldNamePrefix = this.form.fieldNamePrefix;
	        fieldName = Ext.String.startsWith (fieldName, fieldNamePrefix) ? fieldName.substring(fieldNamePrefix.length) : fieldName;
	        
	        var referenceFieldPath  = [];
	        
	        var pathSegments = fieldName.split('.');
	        for (var i=0; i < pathSegments.length; i++)
	        {
	            // Remove repeater entry from path
	            if (!/^[0-9]+$/.test(pathSegments[i]))
	            {
	                referenceFieldPath.push(pathSegments[i]);
	            }
	        }
	        
	        var referenceField = referenceFieldPath.join('.');
	        
	        var value = this.getValue();
	        if (Ext.isObject(value) && value.value)
	        {
	            value = value.value;
	        }
	        value = Ext.Array.from(value);
	        
	        if (value.length > 0)
	        {
	            // Defer the call to let the focus happen before opening the tool.
	            Ext.defer(Ametys.tool.ToolsManager.openTool, 1, Ametys.tool.ToolsManager, ['uitool-search-referencing-contents-with-same-values', {
	                contentId: this.contentInfo.contentId,
	                referenceField: referenceField,
	                referenceValues: value,
	                modelId: this.searchModelIdForContentsWithSameReferencing,
	                id: referenceField + ';' + value.sort().join('-'),
	                startSearchAtOpening: true
	            }]);
	        }
        }
        else
        {
            this.getLogger().warn({message: "Missing contentInfo/contentId property : search on contents with same referenced values is not available ouside a content"});
        }
    	
    },
    
    onAdded: function(container, pos, instanced)
    {
        if (this.allowEdition === null || this.allowEdition === undefined)
        {
            // Forcing false, otherwise the super will put it to true when in a grid (that we don't want for reference tables)
            this.allowEdition = false;
        }

        this.callParent(arguments);
    }  
});