import '../labeledField/labeledFormField.scss';
import './dropdownField.scss';
import '../searchField/searchField.scss';
import IconSearch from '/svg/ic_search.svg';
import { Table } from "view/cmp/table/Table.jsx";
import { textFilter } from "text/String.TextFilter.jsx";
import Input from "view/cmp/field/Input.jsx";

const noHighlight = {
    highlight: (a)=>a
};
const DropdownField = D.declare('view.cmp.DropdownField', function(cfg, children){
    this.textTpl = this.valueItemTpl = (item,me)=>me?me.highlight(item.name,dropStore.get('filterText')):item.name;

    this.valueTpl = items=>D.join(items.map((item, i)=>this.valueItemTpl(item,noHighlight)), ', ');
    Object.assign(this, cfg);
    let isOpen = this.isOpen = new Store.Value.Boolean(false);
    if(!cfg.bind)
        cfg.bind = {sub: ()=>{console.error('BIND FOR DROPDOWN IS NOT SPECIFIED')}, set: ()=>{}, get: ()=>{}}


    let table;
    let dropStore = new Store({
        filterText: ''
    });
    let action = this.action = {
        CHANGE_JOB: function(set, item) {
            if(cfg.singlevalue === true){
                cfg.bind.set(void 0);
                cfg.bind.set(item);
                isOpen.set(false);
                table.updateChildren();
            }else{
                let vals = cfg.bind.get();
                if( set ){
                    vals = vals.concat( item )
                }else{
                    vals = vals.filter( v => v.name !== item.name );
                }
                cfg.bind.set(vals);
                if(cfg.multivalue === false){
                    isOpen.set(false);
                    table.removeChildByData(item, false);
                    dropStore.set('filterText', '');
                }
            }

        },
        CLEAR: function () {
            dropStore.set('filterText', '');
        },
        BLUR: function () {
            minput && minput.blur();
        }
    };

    let listen = (e) => {
        let target = e.target;
        do{
            if(target === this.dom){
                return;
            }
        }while((target = target.parentNode));
        isOpen.set(false);
    }, minput;

    isOpen.hook((v)=>{
        if(v === true){
            document.addEventListener('click', listen);
        }else{
            document.removeEventListener('click', listen);
        }
    });

    this.dom = <div class="form-field">
        <div class="form-field__label">
            <span class="form-field__label-text">{cfg.label}</span>
            <div class={D.cls('dropdown-field', {
                'dropdown-field--opened': isOpen
            })} >
                {cfg.input
                  ? <div className="form-field__wrapper">
                        {minput = <Input type="text" class="form-field__input form-field__input--selection" bind={dropStore.bind('filterText')}
                             placeholder={cfg.placeholder} on={{
                                 focus: ()=>isOpen.set(true),
                                  keydown:(e)=>{
                                     if(e.key === 'Enter'){
                                         cfg.onEnter && cfg.onEnter(dropStore.get('filterText'));
                                     }
                                  }
                             }}/>}
                      <span className="form-field__indicator"/>
                  </div>
                  : <button class="dropdown-field__toggler" on={{ click: () => isOpen.toggle() }}>
                    <span class={D.cls(
                      "dropdown-field__placeholder", {
                          "dropdown-field__placeholder--filled": _=>cfg.bind.sub(val=>_(!!(cfg.multivalue ? val && val.length : val && val.name)))
                      } )}>{_ => {
                        cfg.bind.sub( val => {
                            if( val && ( cfg.multivalue ? val.length : val && val.name ) ){
                                if( cfg.multivalue ){
                                    _( this.valueTpl( val, table ) )
                                }else{
                                    _( this.valueItemTpl( val ) )
                                }
                            }else{
                                _( cfg.placeholder );
                            }
                        } );
                    }}</span>
                  </button>
                }
                <div class="dropdown-field__tooltip">
                    {children}
                    {cfg.filterBox
                      ? <div class="dropdown-field__search">
                            <div class="dropdown-field__search-field">
                                <label className="search-field">
                                    <IconSearch width={"20"} height={"20"}/>
                                    <Input type="search" class="search-field__input" bind={dropStore.bind('filterText')} placeholder={cfg.placeholder || 'Выбрать из списка'}/>
                                </label>
                                {/*<div class="dropdown-field__search-clear">*/}
                                    {/*<IconClose width={"20"} height={"20"}/>*/}
                                {/*</div>*/}
                            </div>
                            <button class="dropdown-field__clear" type={"button"} onClick={()=>dropStore.set('filterText','')}>Сбросить</button>
                        </div>
                      : null}
                    {table = this.table = new Table({
                        sorters: [{id: 'title', type: String}],
                        sort: [{title: 'asc'}],
                        filterFn: function(text, me) {
                            if(cfg.filterFn){
                                if( !cfg.filterFn.call( this, text, me ) ){
                                    return false;
                                }
                            }
                            if(cfg.singlevalue){
                                return this.name !== cfg.bind.get().name;
                            }
                            return (cfg.multivalue ?(text ? textFilter(this.name.toLowerCase(), text) : true):
                              cfg.bind.get().filter( i => i.name === this.name ).length === 0 && (text ? textFilter(this.name.toLowerCase(), text):true))
                        },
                        childrenEl: <ul className={cfg.multivalue?"dropdown-field__list":"form-field__selection-list"}/>,
                        itemTpl: (item, me, bonus)=>{
                            if(cfg.multivalue){
                                return <li>
                                    <label className="picker-button picker-button--admin picker-button--multiple">
                                        <input
                                          checked={cfg.bind.get().filter( i => i.name === item.name ).length === 1}
                                          type="checkbox" className="picker-button__field" onChange={
                                            ( e ) =>
                                              action.CHANGE_JOB( e.currentTarget.checked, item )
                                        }/>
                                        <span className="picker-button__indicator"/>
                                        <span className="picker-button__desc">{this.textTpl.call( me, item, me )}</span>
                                    </label>
                                </li>;
                            }else{
                                return <li  onClick={
                                    ( e ) =>
                                      action.CHANGE_JOB( true, item )
                                }>
                                        <span className="picker-button__desc">{this.textTpl.call( me, item, me )}</span>
                                    </li>;
                            }
                        },
                        emptyTpl: cfg.emptyTpl || ((items)=><li>Нет должностей</li>),
                        items: []
                    })}
                </div>
            </div>
        </div>
    </div>;

    cfg.items && cfg.items.sub(items=>{
        table.items = items || [];
        table.updateChildren();
    });
    cfg.bind.sub( Store.debounce(val => {
        console.log('items changed',val)
        table.updateChildren();
    }, 100));
    dropStore.sub('filterText', Store.debounce(function(text) {
        table.filterText = (text+'').trim().toLowerCase();
        table.updateChildren();
    }, 200));
});

export default DropdownField;
export {DropdownField};
