/**
 * 内部的に使われる{@link Ext.form.field.ComboBox ComboBox}のデータビュー。
 */
Ext.define('Ext.view.BoundList', {
    extend: 'Ext.view.View',
    alias: 'widget.boundlist',
    alternateClassName: 'Ext.BoundList',
    requires: ['Ext.layout.component.BoundList', 'Ext.toolbar.Paging'],

    mixins: [
        'Ext.mixin.Queryable'
    ],

    /**
     * @cfg {Number} [pageSize=0]
     * `0`より大きい場合には、リストの下部に{@link Ext.toolbar.Paging}が表示され、ストアクエリはページ{@link Ext.data.operation.Read#start start}および{@link Ext.data.operation.Read#limit limit}のパラメータと共に実行されます。
     */
    pageSize: 0,

    /**
     * @cfg {String} [displayField=""]
     * ストアからビューに表示するフィールド。
     */

    /**
     * @property {Ext.toolbar.Paging} pagingToolbar
     * このviewのPagingToolbarインスタンスへの参照。設定されるのは、{@link #pageSize}がゼロより大きく、BoundList がレンダリングされている場合だけです。
     */

    // private overrides
    baseCls: Ext.baseCSSPrefix + 'boundlist',
    itemCls: Ext.baseCSSPrefix + 'boundlist-item',
    listItemCls: '',
    shadow: false,
    trackOver: true,

    // This flag indicates to any floaters shown above it that they should focus themselves when taking over topmost position.
    // ZIndexManager#onCollectionSort decides whether to focus the new front component depending on whether the oldFront
    // had focusOnToFront set. Even though this class is in fact not focusable.
    //focusOnToFront: true,

    preserveScrollOnRefresh: true,
    enableInitialSelection: false,

    componentLayout: 'boundlist',

    navigationModel: 'boundlist',

    autoScroll: true,

    childEls: [
        'listWrap', 'listEl'
    ],

    renderTpl: [
        '<div id="{id}-listWrap" data-ref="listWrap" role="presentation" class="{baseCls}-list-ct ', Ext.dom.Element.unselectableCls, '">',
            '<ul id="{id}-listEl" data-ref="listEl" class="' + Ext.plainListCls + '">',
            '</ul>',
        '</div>',
        '{%',
            'var pagingToolbar=values.$comp.pagingToolbar;',
            'if (pagingToolbar) {',
                'Ext.DomHelper.generateMarkup(pagingToolbar.getRenderTree(), out);',
            '}',
        '%}',
        {
            disableFormats: true
        }
    ],

    /**
     * @cfg {String/Ext.XTemplate} tpl
     * 内部のテンプレートに適用するStringもしくはExt.XTemplateのインスタンス。
     *
     * {@link Ext.view.BoundList}は、{@link Ext.form.field.ComboBox}のドロップダウンリストに使われます。以下のようにすれば、テンプレートをカスタマイズできます。
     *
     *     Ext.create('Ext.form.field.ComboBox', {
     *         fieldLabel   : 'State',
     *         queryMode    : 'local',
     *         displayField : 'text',
     *         valueField   : 'abbr',
     *         store        : Ext.create('StateStore', {
     *             fields : ['abbr', 'text'],
     *             data   : [
     *                 {"abbr":"AL", "name":"Alabama"},
     *                 {"abbr":"AK", "name":"Alaska"},
     *                 {"abbr":"AZ", "name":"Arizona"}
     *                 //...
     *             ]
     *         }),
     *         listConfig : {
     *             tpl : '<tpl for="."><div class="x-boundlist-item">{abbr}</div></tpl>'
     *         }
     *     });
     *
     * デフォルト値:
     *
     *     Ext.create('Ext.XTemplate',
     *         '<ul><tpl for=".">',
     *             '<li role="option" class="' + itemCls + '">' + me.getInnerTpl(me.displayField) + '</li>',
     *         '</tpl></ul>'
     *     );
     *
     */

    focusable: false,

    initComponent: function() {
        var me = this,
            baseCls = me.baseCls,
            itemCls = me.itemCls;

        me.selectedItemCls = baseCls + '-selected';
        if (me.trackOver) {
            me.overItemCls = baseCls + '-item-over';
        }
        me.itemSelector = "." + itemCls;
        me.scrollerSelector = 'ul.' + Ext.plainListCls;

        if (me.floating) {
            me.addCls(baseCls + '-floating');
        }

        if (!me.tpl) {
            // should be setting aria-posinset based on entire set of data
            // not filtered set
            me.tpl = new Ext.XTemplate(
                '<tpl for=".">',
                    '<li role="option" unselectable="on" class="' + itemCls + '">' + me.getInnerTpl(me.displayField) + '</li>',
                '</tpl>'
            );
        } else if (!me.tpl.isTemplate) {
            me.tpl = new Ext.XTemplate(me.tpl);
        }

        if (me.pageSize) {
            me.pagingToolbar = me.createPagingToolbar();
        }

        me.callParent();

        // The dropdown is never focused. Key navigation events flow through the input field.
        me.getSelectionModel().preventFocus = true;
    },

    getRefOwner: function() {
        return this.pickerField || this.callParent();
    },

    getRefItems: function() {
        var result = this.callParent(),
            toolbar = this.pagingToolbar;
        
        if (toolbar) {
            result.push(toolbar);
        }
        return result;
    },

    createPagingToolbar: function() {
        return Ext.widget('pagingtoolbar', {
            id: this.id + '-paging-toolbar',
            pageSize: this.pageSize,
            store: this.dataSource,
            border: false,
            ownerCt: this,
            ownerLayout: this.getComponentLayout()
        });
    },

    getNodeContainer: function() {
        return this.listEl;
    },

    refresh: function(){
        var me = this,
            tpl = me.tpl,
            toolbar = me.pagingToolbar,
            rendered = me.rendered;

        // Allow access to the context for XTemplate scriptlets
        tpl.field = me.pickerField;
        tpl.store = me.store;
        me.callParent();
        tpl.field =  tpl.store = null;

        // The view removes the targetEl from the DOM before updating the template
        // Ensure the toolbar goes to the end
        if (rendered && toolbar && toolbar.rendered && !me.preserveScrollOnRefresh) {
            me.el.appendChild(toolbar.el, true);
        }
    },

    bindStore : function(store, initial) {
        var toolbar = this.pagingToolbar;

        this.callParent(arguments);
        if (toolbar) {
            toolbar.bindStore(store, initial);
        }
    },

    /**
     * リスト内のアイテムを表示するために、内部のテンプレートを返すメソッド。このメソッドは、テキストと一緒にアイコンを挿入するなど、より複雑な表示値を使用する場合に上書きするのに便利です。
     *
     * XTemplateの作成時には、コンテキストへのアクセスを提供するため、`field`プロパティの中の所有するフォームフィールドへの参照を渡します。例えば、現在入力中の値を強調表示するには、ComboBoxの{@link Ext.form.field.ComboBox#listConfig listConfig}の一部としてgetInnerTplを設定します。
     *
     *    listConfig:{ getInnerTpl: function() { return '{[values.name.replace(this.field.getRawValue(), "<b>" + this.field.getRawValue() + "</b>")]}'; } }
     * @param {String} displayField BoundListの{@link #displayField}。
     * @return {String} 内部テンプレート。
     */
    getInnerTpl: function(displayField) {
        return '{' + displayField + '}';
    },

    onDestroy: function() {
        this.callParent();
        Ext.destroyMembers(this, 'pagingToolbar', 'listWrap', 'listEl');
    },

    privates: {
        getTargetEl: function() {
            return this.listEl;
        },

        getOverflowEl: function() {
            return this.listWrap;
        },

        // Do the job of a container layout at this point even though we are not a Container.
        finishRenderChildren: function () {
            var toolbar = this.pagingToolbar;

            this.callParent(arguments);

            if (toolbar) {
                toolbar.finishRender();
            }
        }
    }
});