/*
 *  Copyright 2024 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.
 */

/**
 * An automatic columns layout
 */
Ext.define('Ametys.plugins.cms.search.EnhancedColumnsLayout', {
    extend: "Ext.layout.container.Anchor",
    
    alias: 'layout.enhancedcolumns',
    
    innerCtCls: /*Ext.layout.container.Auto.prototype.innerCtCls (firefox does not support the display: table-cell of this class with the columns-count property) +*/ ' enhanced-columns-layout',
    
    /**
     * @config {Number} minColWidth=100 The minimal column width
     */
    minColWidth: 100,
    /**
     * @config {Function} ignoreItem A function to test if an item will not be displayed and should ignored. This is usefull since we do not use items heights but just count them. 
     * @config {Function} ignoreItem.item The item to test 
     * @config {Function} ignoreItem.returns true if the item should be ignored 
     */
    /**
     * @private
     * @property {Number} _nbColumns The number of columns
     */
    _nbColumns: 1,
    
    _computeColumns: function()
    {
        let width = this.owner.getWidth();
        if (this._lastWidth != width 
            || !this.owner.body.first().first().dom.style.columnCount)
        {
            this._lastWidth = width;
        
            this._nbColumns = Math.max(1, Math.floor(width / this.minColWidth));
            let colWidth = Math.floor(1000 / this._nbColumns) / 10;

            this.owner.items.each(function(item) { item.anchor = colWidth + '%'; });
            this.owner.items.each(function(item) { item.updateLayout(); }); // required otherwise at loading sometime we will stay on 1 column

            this.owner.body.first().first().dom.style.columnCount = this._nbColumns;
        }
    },
    
    calculateItems: function(ownerContext, containerSize) {
        let v = this.callParent(arguments);

        let target = this.getRenderTarget();
                
        // Add missing columns
        let startingCols = target.query(":scope > *.col");
        for (let i = 0; i < this._nbColumns - startingCols.length; i++)
        {
            target.createChild({ tag: "div", cls: "col" });
        }

        let finalCols = target.query(":scope > *.col");
        let items = this.getLayoutItems();

        // Move items in the right column
        let ignoredItems = 0;
        let ignoreItem = this.getInitialConfig('ignoreItem');
        
        let positions = [];
        finalCols.forEach(c => positions.push(0));
        
        for (let i = 0; i < items.length; i++) 
        {
            let item = items[i];
            if (ignoreItem && ignoreItem(item))
            {
                ignoredItems++;
                continue;
            }
            
            let targetCol = finalCols[(i - ignoredItems) % this._nbColumns];
            
            if (!this._isValidParent(item.getEl().parent().dom, targetCol, positions[targetCol]))
            {
                this.moveItem(item, targetCol, positions[targetCol]);
            }
            
            positions[targetCol]++;
        }
        
        // Remove unused (empty) columns
        for (let i = finalCols.length; i > this._nbColumns; i--) 
        {
            finalCols[i - 1].remove();
        }
        
        return v;
    },
    
    _isValidParent: function(item, target, position) {
        if (item != target)
        {
            return false;
        }
        else if (position === undefined)
        {
            return true;
        }
        else
        {
            return target.childNodes[position] == item;
        }
    },
    
    isValidParent: function(item, target, position) {
        return true
    },

    calculateContentSize: function(ownerContext) 
    {
        this._computeColumns();

        this.callParent(arguments);
    }
});