/**
 * This layout manager is used to center contents within a container. As a subclass of
 * {@link Ext.layout.container.Fit fit layout}, CenterLayout expects to have one child
 * item; multiple items will be placed overlapping. The layout does not require any config
 * options. Items in the container can use percentage width or height rather than be fit
 * to the full size of the container.
 *
 * Example usage:
 *
 *      // The content panel is centered in the container
 *
 *      var p = Ext.create('Ext.Panel', {
 *          title: 'Center Layout',
 *          layout: 'center',
 *          items: [{
 *              title: 'Centered Content',
 *              width: '75%',  // assign 75% of the container width to the item
 *              html: 'Some content'
 *          }]
 *      });
 *
 * If you leave the title blank and specify no border you can create a non-visual, structural
 * container just for centering the contents.
 *
 *      var p = Ext.create('Ext.Container', {
 *          layout: 'center',
 *          items: [{
 *              title: 'Centered Content',
 *              width: 300,
 *              height: '90%', // assign 90% of the container height to the item
 *              html: 'Some content'
 *          }]
 *      });
 */
Ext.define('Ext.layout.container.Center', {
    extend: 'Ext.layout.container.Fit',
    alternateClassName: 'Ext.ux.layout.Center',
    
    alias: [
        'layout.center',
        'layout.ux.center'
    ],
 
    type: 'center',
    
    percentRe: /^\d+(?:\.\d+)?%$/,
 
    itemCls: Ext.baseCSSPrefix + 'center-layout-item',
 
    childEls: [
        'targetEl'
    ],
 
    /* eslint-disable indent, max-len */
    renderTpl: [
        '<div id="{ownerId}-targetEl" data-ref="targetEl" class="{targetElCls}" role="presentation">' +
            '{%this.renderBody(out, values)%}' +
        '</div>'
    ],
    /* eslint-enable indent, max-len */
 
    targetElCls: Ext.baseCSSPrefix + 'center-target',
 
    beginLayout: function(ownerContext) {
        var me = this,
            percentRe = me.percentRe,
            childItems, len, i, itemContext, item;
 
        me.callParent([ownerContext]);
        
        childItems = ownerContext.childItems;
 
        for (= 0, len = childItems.length; i < len; ++i) {
            itemContext = childItems[i];
            item = itemContext.target;
            
            if (percentRe.test(item.width)) {
                item.getEl().setStyle('width', '');
            }
            
            if (percentRe.test(item.height)) {
                item.getEl().setStyle('height', '');
            }
        }
 
        ownerContext.targetElContext = ownerContext.getEl('targetEl', me);
    },
 
    beginLayoutCycle: function(ownerContext, firstCycle) {
        var targetEl = this.targetEl;
 
        this.callParent([ownerContext, firstCycle]);
        targetEl.setStyle('width', '');
        targetEl.setStyle('height', '');
    },
 
    getRenderData: function() {
        var data = this.callParent();
 
        data.targetElCls = this.targetElCls;
 
        return data;
    },
 
    getRenderTarget: function() {
        return this.targetEl;
    },
 
    getItemSizePolicy: function(item, ownerSizeModel) {
        var me = this,
            sizeModel = ownerSizeModel || me.owner.getSizeModel(),
            percentRe = me.percentRe,
            mode = ((sizeModel.width.shrinkWrap || !percentRe.test(item.width)) ? 0 : 1) |
                  ((sizeModel.height.shrinkWrap || !percentRe.test(item.height)) ? 0 : 2);
 
        return me.sizePolicies[mode];
    },
 
    isItemShrinkWrap: function(item) {
        return true;
    },
 
    calculate: function(ownerContext) {
        var targetElContext = ownerContext.targetElContext,
            info;
 
        this.callParent([ownerContext]);
        info = ownerContext.state.info;
 
        if (ownerContext.widthModel.shrinkWrap) {
            targetElContext.setWidth(info.contentWidth);
        }
 
        if (ownerContext.heightModel.shrinkWrap) {
            targetElContext.setHeight(info.contentHeight);
        }
    },
 
    getPos: function(itemContext, info, dimension) {
        var modelName = dimension + 'Model',
            size = itemContext.props[dimension],
            pos = 0;
 
        if (!itemContext[modelName].calculated) {
            size += info.margins[dimension];
        }
 
        if (!info.ownerContext[modelName].shrinkWrap) {
            pos = Math.round((info.targetSize[dimension] - size) / 2);
 
            if (isNaN(pos)) {
                this.done = false;
            }
        }
 
        return Math.max(pos, 0);
    },
 
    positionItemX: function(itemContext, info) {
        var left = this.getPos(itemContext, info, 'width');
 
        itemContext.setProp('x', left);
    },
 
    positionItemY: function(itemContext, info) {
        var top = this.getPos(itemContext, info, 'height');
 
        itemContext.setProp('y', top);
    },
 
    setItemHeight: function(itemContext, info) {
        var ratio = parseFloat(itemContext.target.height) / 100;
 
        itemContext.setHeight(Math.round((info.targetSize.height - info.margins.height) * ratio));
    },
 
    setItemWidth: function(itemContext, info) {
        var ratio = parseFloat(itemContext.target.width) / 100;
 
        itemContext.setWidth(Math.round((info.targetSize.width - info.margins.width) * ratio));
    }
});