(function() {
    var Ext = window.Ext4 || window.Ext;

    /**
     * @private
     * Gear menu shown by default on rows of Rally.ui.grid.Grids and Rally.ui.cardboard.Cards of boards.
     */
    Ext.define('Rally.ui.menu.DefaultRecordMenu', {
        extend: 'Rally.ui.menu.RecordMenu',
        alias: 'widget.rallydefaultrecordmenu',
        requires: [
            'Ext.menu.Separator',
            'Rally.ui.menu.item.AddChildMenuItem',
            'Rally.ui.menu.item.AddDefectMenuItem',
            'Rally.ui.menu.item.AddExistingTestCasesMenuItem',
            'Rally.ui.menu.item.AddTaskMenuItem',
            'Rally.ui.menu.item.AddTestCaseMenuItem',
            'Rally.ui.menu.item.CopyMenuItem',
            'Rally.ui.menu.item.CopyUserMenuItem',
            'Rally.ui.menu.item.CopyTasksFromMenuItem',
            'Rally.ui.menu.item.DeleteMenuItem',
            'Rally.ui.menu.item.EditMenuItem',
            'Rally.ui.menu.item.InlineAddChildMenuItem',
            'Rally.ui.menu.item.InlineAddPeerMenuItem',
            'Rally.ui.menu.item.MoveToPositionMenuItem',
            'Rally.ui.menu.item.RankExtremeMenuItem',
            'Rally.ui.menu.item.RemoveMenuItem',
            'Rally.ui.menu.item.RunTestSetMenuItem',
            'Rally.ui.menu.item.ShowDetailsMenuItem',
            'Rally.ui.menu.item.SplitMenuItem',
            'Rally.ui.menu.item.WatchMenuItem',
            'Rally.ui.popover.Popover',
            'Rally.ui.menu.item.AddExistingDefectsMenuItem'
        ],

        mixins: {
            messageagble: 'Rally.Messageable'
        },

        config: {

            /**
             * @cfg {Rally.data.Model} record (required)
             * The record to build the menu for
             */
            record: null,

            showAddTasks: true,

            showAddDefects: true,

            showAddTestCases: true,

            showCopyTasksFrom: true,

            showCopyMenuItem: true,

            showInlineAdd: false,

            /**
             * @cfg {Ext.Element|HTMLElement} (optional) owningEl
             * The element this menu item is being invoked against.
             */
            owningEl: undefined,

            /**
             * @cfg {Function} onBeforeRecordMenuCopy
             * Function to execute before copying a record from the gear menu. Return false to not perform the action.
             * @param {Rally.data.Model} record The record that is being acted on.
             */
            onBeforeRecordMenuCopy: Ext.emptyFn,

            /**
             * @cfg {Function} onRecordMenuCopy
             * Function to execute after copying a record from the gear menu.
             * @param {Rally.data.Model} record The record that was acted on.
             */
            onRecordMenuCopy: Ext.emptyFn,

            /**
             * @cfg {Function} onBeforeRecordMenuDelete
             * Function to execute before deleting a record from the gear menu. Return false to not perform the action.
             * @param {Rally.data.Model} record The record that is being acted on.
             */
            onBeforeRecordMenuDelete: Ext.emptyFn,

            /**
             * @cfg {Function} onRecordMenuDelete
             * Function to execute after deleting a record from the gear menu.
             * @param {Rally.data.Model} record The record that was acted on.
             */
            onRecordMenuDelete: Ext.emptyFn,

            /**
             * @cfg {Function} onBeforeRecordMenuRankHighest
             * Function to execute before ranking a record highest from the gear menu. Return false to not perform the action.
             * @param {Rally.data.Model} record The record that is being acted on.
             */
            onBeforeRecordMenuRankHighest: Ext.emptyFn,

            /**
             * @cfg {Function} onBeforeRecordMenuRankLowest
             * Function to execute before ranking a record highest from the gear menu. Return false to not perform the action.
             * @param {Rally.data.Model} record The record that is being acted on.
             */
            onBeforeRecordMenuRankLowest: Ext.emptyFn,

            /**
             * @cfg {Function} onRecordMenuRemove
             * Function to execute after removing a record from the gear menu.
             * @param {Rally.data.Model} record The record that is being acted on.
             */
            onRecordMenuRemove: Ext.emptyFn,

            /**
             * @inheritdoc Rally.ui.menu.RankExtremeMenuItem#rankRecordHelper
             */
            rankRecordHelper: {
                findRecordToRankAgainst: Ext.emptyFn,
                getMoveToPositionStore: Ext.emptyFn
            }
        },

        initComponent: function() {
            this.items = this._getMenuItems();
            this.callParent(arguments);
        },

        _getMenuItems: function() {
            var record = this.getRecord(),
                items = [],
                popoverPlacement = this.popoverPlacement || Rally.ui.popover.Popover.DEFAULT_PLACEMENT;

            if (this.showInlineAdd) {
                items.push({
                    xtype: 'rallyrecordmenuiteminlineaddchild',
                    view: this.view,
                    record: record
                });
                items.push({
                    xtype: 'rallyrecordmenuiteminlineaddpeer',
                    view: this.view,
                    record: record
                });
                items.push({
                    xtype: 'rallyrecordmenuitemaddexistingtestcases',
                    view: this.view,
                    record: record
                });
                items.push({
                    xtype: 'rallyrecordmenuitemaddexistingdefects',
                    view: this.view,
                    record: record
                });
            } else {
                if (this.showAddTasks !== false) {
                    items.push({
                        xtype: 'rallyrecordmenuitemaddtask',
                        record: record,
                        owningEl: this.owningEl,
                        popoverPlacement: popoverPlacement
                    });
                }

                if (this.showAddDefects !== false) {
                    items.push({
                        xtype: 'rallyrecordmenuitemadddefect',
                        record: record,
                        owningEl: this.owningEl,
                        popoverPlacement: popoverPlacement
                    });
                }

                if (this.showAddTestCases !== false) {
                    items.push({
                        xtype: 'rallyrecordmenuitemaddtestcase',
                        record: record,
                        owningEl: this.owningEl,
                        popoverPlacement: popoverPlacement
                    });
                }

                if (this.showAddChildMenuItem !== false) {
                    items.push({
                        xtype: 'rallyrecordmenuitemaddchild',
                        record: record
                    });
                }
            }

            if (this.showCopyTasksFrom !== false) {
                items.push({
                    xtype: 'rallyrecordmenuitemcopytasksfrom',
                    record: record
                });
            }

            items.push({
                xtype: 'menuseparator',
                margin: 0,
                padding: 0
            });

            items.push(
                {
                    xtype: 'rallyrecordmenuitemshowdetails',
                    record: record
                },
                {
                    xtype: 'rallyrecordmenuitemedit',
                    record: record
                },
                {
                    xtype: 'rallyrecordmenuitemruntestset',
                    record: record,
                    actionScope: this
                }
            );

            if (this.showCopyMenuItem !== false) {
                items.push({
                        xtype: 'rallyrecordmenuitemcopy',
                        record: record,
                        beforeAction: this.getOnBeforeRecordMenuCopy(),
                        afterAction: this.getOnRecordMenuCopy(),
                        actionScope: this
                    }
                );
            }

            items.push(
                {
                    xtype: 'rallyrecordmenuitemcopyuser',
                    record: record
                }
            );

            items.push({
                xtype: 'menuseparator',
                margin: 0,
                padding: 0
            });

            if (this.showRankMenuItems !== false &&
                    (!_.isFunction(this.shouldRecordBeExtremeRankable) || this.shouldRecordBeExtremeRankable(record))) {
                items.push(
                    {
                        xtype: 'rallyrecordmenuitemrankextreme',
                        rankRecordHelper: this.getRankRecordHelper(),
                        rankPosition: 'highest',
                        record: record,
                        beforeAction: this.getOnBeforeRecordMenuRankHighest(),
                        actionScope: this
                    },
                    {
                        xtype: 'rallyrecordmenuitemrankextreme',
                        rankRecordHelper: this.getRankRecordHelper(),
                        rankPosition: 'lowest',
                        record: record,
                        beforeAction: this.getOnBeforeRecordMenuRankLowest(),
                        actionScope: this
                    }
                );

                if (!_.isFunction(this.shouldRecordBeRankable) || this.shouldRecordBeRankable(record)) {
                    items.push(
                        {
                            xtype: 'rallyrecordmenuitemmovetoposition',
                            record: record,
                            rankRecordHelper: this.getRankRecordHelper()
                        }
                    );
                }

                items.push(
                    {
                        xtype: 'menuseparator',
                        margin: '0 0 0 0',
                        padding: '0 0 0 0'
                    });
            }

            if (this.showSplitMenuItem !== false) {
                items.push(
                    {
                        xtype: 'rallyrecordmenuitemsplit',
                        record: record
                    },
                    {
                        xtype: 'menuseparator',
                        margin: '0 0 0 0',
                        padding: '0 0 0 0'
                    }
                );
            }

            if (this.showWatchMenuItem !== false && Rally.data.notifications.Api.enabled) {
                items.push(
                    {
                        xtype: 'rallyrecordmenuitemwatch',
                        record: record,
                        actionScope: this,
                        enableBetaBadge: true
                    },
                    {
                        xtype: 'menuseparator',
                        margin: '0 0 0 0',
                        padding: '0 0 0 0'
                    }
                );
            }

            if (this.collectionStore && _.isFunction(this.shouldBeRemovable) && this.shouldBeRemovable(record)) {
                items.push({
                    xtype: 'rallyrecordmenuitemremove',
                    actionScope: this,
                    afterAction: this.onRecordMenuRemove,
                    collectionStore: this.collectionStore,
                    record: record
                });
            }

            if (this.showDeleteMenuItem !== false) {
                items.push(
                    {
                        xtype: 'rallyrecordmenuitemdelete',
                        record: record,
                        beforeAction: this.getOnBeforeRecordMenuDelete(),
                        afterAction: this.getOnRecordMenuDelete(),
                        actionScope: this
                    }
                );
            }

            return items;
        }
    });
})();