YUI.add('aui-layout-builder-add-row', function (A, NAME) {

/**
 * The Layout Add Row Component
 *
 * @module aui-layout-add-row
 */

var CSS_ADD_ROW = A.getClassName('layout', 'builder', 'add', 'row'),
    CSS_ADD_ROW_AREA = A.getClassName('layout', 'builder', 'add', 'row', 'area'),
    CSS_ADD_ROW_SMALL_SCREEN = A.getClassName('layout', 'builder', 'add', 'row', 'small', 'screen'),
    CSS_ADD_ROW_SMALL_SCREEN_AREA = A.getClassName('layout', 'builder', 'add', 'row', 'small', 'screen', 'area'),
    CSS_ADD_ROW_AREA_FIXED = A.getClassName('layout', 'builder', 'add', 'row', 'area', 'fixed'),
    CSS_ADD_ROW_CHOOSE_ROW = A.getClassName('layout', 'builder', 'add', 'row', 'choose', 'row'),

    TPL_ADD_ROW_AREA = '<div class="' + [CSS_ADD_ROW_AREA, CSS_ADD_ROW_AREA_FIXED].join(' ') + '"></div>',
    TPL_ADD_ROW_CHOOSE_ROW = '<div class="' + CSS_ADD_ROW_CHOOSE_ROW + ' ' + CSS_ADD_ROW + '">{addRow}</div>',
    TPL_ADD_ROW_SMALL_SCREEN_SIZE = '<div class="' + [CSS_ADD_ROW, CSS_ADD_ROW_SMALL_SCREEN_AREA].join(' ') +
        '"><div class="' + CSS_ADD_ROW_SMALL_SCREEN + '"></div><div>{addRow}</div></div>';

/**
 * A base class for Layout Add Row.
 *
 * @class A.LayoutBuilderAddRow
 * @param {Object} config Object literal specifying layout configuration
 *     properties.
 */
function LayoutBuilderAddRow() {}

LayoutBuilderAddRow.prototype = {

    /**
     * Area to choose a new type of row.
     *
     * @property addRowArea
     * @type {Node}
     */
    addRowArea: null,

    /**
     * Body's node.
     *
     * @property _bodyNode
     * @type {Node}
     * @protected
     */
    _bodyNode: null,

    /**
     * Construction logic executed during instantiation.
     * Lifecycle.
     *
     * @method initializer
     * @protected
     */
    initializer: function() {
        this.addRowArea = this._createAddRowArea();
        this._addRowAreaForSmallScreens = this._createAddRowAreaForSmallScreens();

        this._bodyNode = A.one('body');

        this._eventHandles.push(
            this.after('enableAddRowsChange', this._afterEnableAddRowsChange)
        );

        this._uiSetEnableAddRows(this.get('enableAddRows'));
    },

    /**
     * Destructor implementation for the `A.LayoutBuilderAddRow` class. Lifecycle.
     *
     * @method destructor
     * @protected
     */
    destructor: function() {
        this._unbindAddRowEvents();
    },

    /**
     * Adds the appropriate add row area to container.
     *
     * @method _addAppropriateAddRowArea
     * @protected
     */
    _addAppropriateAddRowArea: function() {
        var container = this.get('container');

        if (this.get('layout').get('isColumnMode')) {
            this._addRowAreaForSmallScreens.remove();
            container.append(this.addRowArea);
        }
        else {
            this.addRowArea.remove();
            container.append(this._addRowAreaForSmallScreens);
        }
    },

    /**
     * Add a row to layout.
     *
     * @method _addRow
     * @param {Node} button
     * @protected
     */
    _addRow: function(button) {
        var numberOfCols = button.getData('numberOfCols');

        this.get('layout').addRowWithSpecifiedColNumber(numberOfCols);

        window.scrollTo(0, A.DOM.region(this._layoutContainer._node).bottom);
    },

    /**
     * Fired after the `rows` attribute changes.
     *
     * @method _afterAddRowRowsChange
     * @protected
     */
    _afterAddRowRowsChange: function() {
        this._setAddRowAreaPosition();
    },

    /**
     * Fired after the window's resize.
     *
     * @method _afterAddRowWindowResize
     * @protected
     */
    _afterAddRowWindowResize: function() {
        this._setAddRowAreaPosition();
    },

    /**
     * Fired after `isColumnMode` changes.
     *
     * @method _afterAddRowIsColumnModeChange
     * @protected
     */
    _afterAddRowIsColumnModeChange: function() {
        this._addAppropriateAddRowArea();
        this._setAddRowAreaPosition();
    },

    /**
     * Fired after the `enableAddRows` attribute changes.
     *
     * @method _afterEnableAddRowsChange
     * @protected
     */
    _afterEnableAddRowsChange: function() {
        this._uiSetEnableAddRows(this.get('enableAddRows'));
    },

    /**
     * Binds the necessary events for the functionality of adding rows to the
     * layout.
     *
     * @method _bindAddRowEvents
     * @protected
     */
    _bindAddRowEvents: function() {
        var instance = this,
            container = this.get('container');

        this._bodyNode.plug(A.Plugin.ScrollInfo);

        this._bodyNode.scrollInfo.on('scroll', function() {
            instance._setAddRowAreaPosition();
        });

        this._addRowsEventHandles = [
            container.delegate('click', A.bind(this._onMouseClickAddRowEvent, this), '.' + CSS_ADD_ROW),
            container.delegate('key', A.bind(this._onKeyPressAddRowEvent, this), 'press:13', '.' + CSS_ADD_ROW),
            this.after('layout:rowsChange', A.bind(this._afterAddRowRowsChange, this)),
            this.after('layout:isColumnModeChange', A.bind(this._afterAddRowIsColumnModeChange, this)),
            A.on('windowresize', A.bind(this._afterAddRowWindowResize, this))
        ];
    },

    /**
     * Creates the area to choose the new row.
     *
     * @method _createAddRowArea
     * @protected
     */
    _createAddRowArea: function() {
        var rowArea = A.Node.create(TPL_ADD_ROW_AREA),
            rowOption;

        rowOption = A.Node.create(A.Lang.sub(TPL_ADD_ROW_CHOOSE_ROW, {
            addRow: this.get('strings').addRow
        }));
        rowOption.setData('numberOfCols', 1);

        rowArea.append(rowOption);

        return rowArea;
    },

    /**
     * Creates the area to add new row for smartphone.
     *
     * @method _createAddRowAreaForSmallScreens
     * @protected
     */
    _createAddRowAreaForSmallScreens: function() {
        var rowArea = A.Node.create(A.Lang.sub(TPL_ADD_ROW_SMALL_SCREEN_SIZE, {
            addRow: this.get('strings').addRow
        }));

        rowArea.setData('numberOfCols', 1);

        return rowArea;
    },

    /**
     * Fired on `key:press` event for the add row button.
     *
     * @method _onKeyPressAddRowEvent
     * @param {EventFacade} event
     * @protected
     */
    _onKeyPressAddRowEvent: function(event) {
        this._addRow(event.target);
    },

    /**
     * Fires after click on add row button.
     *
     * @method _onMouseClickEvent
     * @param {EventFacade} event
     * @protected
     */
    _onMouseClickAddRowEvent: function(event) {
        this._addRow(event.target);
        this._setAddRowAreaPosition();
    },

    /**
     * Removes current add row template.
     *
     * @method _removeAddRowTemplate
     * @protected
     */
    _removeAddRowTemplate: function() {
        this.addRowArea.remove();
        this._addRowAreaForSmallScreens.remove();
    },

    /**
     * Sets row area to fixed or relative depending on it's position.
     *
     * @method _setAddRowAreaPosition
     * @protected
     */
    _setAddRowAreaPosition: function() {
        var addRowArea,
            bodyBottom = this._bodyNode.scrollInfo.getScrollInfo().scrollBottom,
            layoutContainerBottom = this._layoutContainer.get('region').bottom;

        if (this.addRowArea.get('parentNode')) {
            addRowArea = this.addRowArea;
        }
        else {
            addRowArea = this._addRowAreaForSmallScreens;
        }

        if (bodyBottom < layoutContainerBottom) {
            addRowArea.addClass(CSS_ADD_ROW_AREA_FIXED);
        }
        else if (bodyBottom >= layoutContainerBottom && addRowArea.hasClass(CSS_ADD_ROW_AREA_FIXED)) {
            addRowArea.removeClass(CSS_ADD_ROW_AREA_FIXED);
            window.scrollBy(0, addRowArea.get('region').height);
        }
    },

    /**
     * Updates the UI according to the value of the `enableAddRows` attribute.
     *
     * @method _uiSetEnableAddRows
     * @param {Boolean} enableAddRows
     * @protected
     */
    _uiSetEnableAddRows: function(enableAddRows) {
        if (enableAddRows) {
            this._addAppropriateAddRowArea();
            this._bindAddRowEvents();
            this._setAddRowAreaPosition();
        }
        else {
            this._removeAddRowTemplate();
            this._unbindAddRowEvents();
        }
    },

    /**
     * Unbinds the events related to the functionality of adding rows to the
     * layout.
     *
     * @method _unbindAddRowEvents
     * @protected
     */
    _unbindAddRowEvents: function() {
        this._bodyNode.unplug(A.Plugin.ScrollInfo);

        if (this._addRowsEventHandles) {
            (new A.EventHandle(this._addRowsEventHandles)).detach();
        }
    }
};

/**
 * Static property used to define the default attribute configuration for the
 * `A.LayoutBuilderAddRow`.
 *
 * @property ATTRS
 * @type {Object}
 * @static
 */
LayoutBuilderAddRow.ATTRS = {
    /**
     * Flag indicating if the feature of adding rows to the layout is
     * enabled or not.
     *
     * @attribute enableAddRows
     * @default true
     * @type {Boolean}
     */
    enableAddRows: {
        validator: A.Lang.isBoolean,
        value: true
    }
};

A.LayoutBuilderAddRow = LayoutBuilderAddRow;


}, '3.1.0-deprecated.110', {"requires": ["aui-node-base", "base-build", "node-scroll-info"], "skinnable": true});
