/**
 * @class Ext.layout.container.AbstractCard
 * @extends Ext.layout.container.Fit
 * <p>This layout manages multiple child Components, each is fit to the Container, where only a single child Component
 * can be visible at any given time.  This layout style is most commonly used for wizards, tab implementations, etc.
 * This class is intended to be extended or created via the layout:'card' {@link Ext.container.Container#layout} config,
 * and should generally not need to be created directly via the new keyword.</p>
 * <p>The CardLayout's focal method is {@link #setActiveItem}.  Since only one panel is displayed at a time,
 * the only way to move from one Component to the next is by calling setActiveItem, passing the id or index of
 * the next panel to display.  The layout itself does not provide a user interface for handling this navigation,
 * so that functionality must be provided by the developer.</p>
 * <p>Containers that are configured with a card layout will have a method setActiveItem dynamically added to it.
 * <pre><code>
      var p = new Ext.panel.Panel({
          fullscreen: true,
          layout: 'card',
          items: [{
              html: 'Card 1'
          },{
              html: 'Card 2'
          }]
      });
      p.setActiveItem(1);
   </code></pre>
 * </p>
 */


Ext.define('Ext.layout.container.AbstractCard', {

   
/* Begin Definitions */

    extend
: 'Ext.layout.container.Fit',

   
/* End Definitions */

    type
: 'card',

    sizeAllCards
: false,

    hideInactive
: true,

    /**
     * @cfg {Boolean} deferredRender
     * True to render each contained item at the time it becomes active, false to render all contained items
     * as soon as the layout is rendered (defaults to false).  If there is a significant amount of content or
     * a lot of heavy controls being rendered into panels that are not displayed by default, setting this to
     * true might improve performance.
     */

    deferredRender
: false,

    beforeLayout
: function() {
       
var me = this;
        me
.activeItem = me.getActiveItem();
       
if (me.activeItem && me.deferredRender) {
            me
.renderItems([me.activeItem], me.getRenderTarget());
           
return true;
       
}
       
else {
           
return this.callParent(arguments);
       
}
   
},

    onLayout
: function() {
       
var me = this,
            activeItem
= me.activeItem,
            items
= me.getVisibleItems(),
            ln
= items.length,
            targetBox
= me.getTargetBox(),
            i
, item;

       
for (i = 0; i < ln; i++) {
            item
= items[i];
            me
.setItemBox(item, targetBox);
       
}

       
if (!me.firstActivated && activeItem) {
           
if (activeItem.fireEvent('beforeactivate', activeItem) !== false) {
                activeItem
.fireEvent('activate', activeItem);
           
}
            me
.firstActivated = true;
       
}
   
},

    isValidParent
: function(item, target, position) {
       
// Note: Card layout does not care about order within the target because only one is ever visible.
       
// We only care whether the item is a direct child of the target.
       
var itemEl = item.el ? item.el.dom : Ext.getDom(item);
       
return (itemEl && itemEl.parentNode === (target.dom || target)) || false;
   
},

    /**
     * Return the active (visible) component in the layout.
     * @returns {Ext.Component}
     */

    getActiveItem
: function() {
       
var me = this;
       
if (!me.activeItem && me.owner) {
            me
.activeItem = me.parseActiveItem(me.owner.activeItem);
       
}

       
if (me.activeItem && me.owner.items.indexOf(me.activeItem) != -1) {
           
return me.activeItem;
       
}

       
return null;
   
},

   
// @private
    parseActiveItem
: function(item) {
       
if (item && item.isComponent) {
           
return item;
       
}
       
else if (typeof item == 'number' || item === undefined) {
           
return this.getLayoutItems()[item || 0];
       
}
       
else {
           
return this.owner.getComponent(item);
       
}
   
},

   
// @private
    configureItem
: function(item, position) {
       
this.callParent([item, position]);
       
if (this.hideInactive && this.activeItem !== item) {
            item
.hide();
       
}
       
else {
            item
.show();
       
}
   
},

    onRemove
: function(component) {
       
if (component === this.activeItem) {
           
this.activeItem = null;
           
if (this.owner.items.getCount() === 0) {
               
this.firstActivated = false;
           
}
       
}
   
},

   
// @private
    getAnimation
: function(newCard, owner) {
       
var newAnim = (newCard || {}).cardSwitchAnimation;
       
if (newAnim === false) {
           
return false;
       
}
       
return newAnim || owner.cardSwitchAnimation;
   
},

    /**
     * Return the active (visible) component in the layout to the next card
     * @returns {Ext.Component}
     */

    getNext
: function(wrap) {
       
//NOTE: Removed the JSDoc for this function's arguments because it is not actually supported in 4.0. This
       
//should come back in 4.1
       
       
var items = this.getLayoutItems(),
            index
= Ext.Array.indexOf(items, this.activeItem);
       
return items[index + 1] || (wrap ? items[0] : false);
   
},

    /**
     * Sets the active (visible) component in the layout to the next card
     */

   
next: function(anim, wrap) {
       
//NOTE: Removed the JSDoc for this function's arguments because it is not actually supported in 4.0. This
       
//should come back in 4.1
       
       
return this.setActiveItem(this.getNext(wrap), anim);
   
},

    /**
     * Return the active (visible) component in the layout to the previous card
     * @returns {Ext.Component}
     */

    getPrev
: function(wrap) {
       
//NOTE: Removed the JSDoc for this function's arguments because it is not actually supported in 4.0. This
       
//should come back in 4.1
       
       
var items = this.getLayoutItems(),
            index
= Ext.Array.indexOf(items, this.activeItem);
       
return items[index - 1] || (wrap ? items[items.length - 1] : false);
   
},

    /**
     * Sets the active (visible) component in the layout to the previous card
     */

    prev
: function(anim, wrap) {
       
//NOTE: Removed the JSDoc for this function's arguments because it is not actually supported in 4.0. This
       
//should come back in 4.1
       
       
return this.setActiveItem(this.getPrev(wrap), anim);
   
}
});