import { Component, Input, forwardRef } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
import { CodeList } from '@global/service/codelist';

@Component({
    selector: 'app-multiple-select',
    templateUrl: './app-multiple-select.html',
    styleUrls: ['./app-multiple-select.scss'],
    providers: [
        {
            provide: NG_VALUE_ACCESSOR,
            useExisting: forwardRef(() => AppMultipleSelect),
            multi: true
        }
    ]
})
export class AppMultipleSelect implements ControlValueAccessor {

    /**
	 * 全部数据对象集合
	 * 
	 * @type {any[]}
	 * @memberof AppMultipleSelect
	 */
    items: any;

    /**
    * 选中数据值集合
    *
    * @private
    * @type any
    * @memberof AppMultipleSelect
    */
    selectedItems: any[] = [];

    /**
	 * 选中数据值
	 *
	 * @private
	 * @type any
	 * @memberof AppMultipleSelect
	 */
    public selectedValues: any;

    /**
    * 选中数据值
    *
    * @private
    * @type any
    * @memberof AppMultipleSelect
    */
    public selectedTexts: any;

    constructor(private $codelist: CodeList) {

    }

    /**
     * 是否启用
     *
     * @type {boolean}
     * @memberof AppMultipleSelect
     */
    @Input()
    disabled: boolean;

    @Input()
    set config(val: any) {
        if (val) {
            this.items = this.$codelist.getCodeItemByTag(val).items;
        }
    }

    /**
     * 提示信息
     *
     * @type {string}
     * @memberof AppMultipleSelect
     */
    @Input()
    placeholder: string;

    /**
     * 模式的类型
     *
     * @type {string}
     * @memberof AppMultipleSelect
     */
    @Input()
    orMode: string = 'str';

    /**
     * 数据存储分隔符
     *
     * @type {string}
     * @memberof AppMultipleSelect
     */
    @Input()
    valueSeparator: string = ',';

    /**
     * 数据显示分隔符
     *
     * @type {string}
     * @memberof AppMultipleSelect
     */
    @Input()
    textSeparator: string = ',';

    /**
     * 获取选择的实际值和文本值
     *
     * @param {any[]} arr
     * @memberof AppMultipleSelect
     */
    public getSelectedValues(arr: any[]) {
        let num = 0;
        let str = '';
        let texts = '';
        arr.forEach(val => {
            const element = this.items.find(item => Object.is(item.value, val));
            if (element) {
                if (this.orMode === 'num') {
                    num = num | parseInt(val, 10);
                } else {
                    if (str) {
                        str += this.valueSeparator;
                    }
                    str += element.value;
                }
                if (texts) {
                    texts += this.textSeparator;
                }
                texts += element.text;
            }
        });
        this.selectedValues = this.orMode === 'num' ? (num !== 0 ? num.toString() : '') : str;
        this.selectedTexts = texts;
    }

    /**
     * 编辑器值
     *
     * @type {string}
     * @memberof AppMultipleSelect
     */
    set value(val: any) {
        if (val && val instanceof Array && !Object.is(JSON.stringify(val), JSON.stringify(this.selectedItems))) {
            this.selectedItems = val;
            this.getSelectedValues(this.selectedItems);
        }
    }

    get value() {
        return this.selectedItems;
    }

    public dataChange($event) {
        if(this.value !== $event.target.value){
            this.value = $event.target.value;
            this.onChange(this.selectedValues);
        }
    }

    /**
     * 输入
     *
     * @param {*} obj
     * @memberof AppMultipleSelect
    */
    public writeValue(obj: any): void {
        if (obj) {
            this.selectedValues = obj;
            if (this.orMode === 'num') {
                const temp = [];
                this.items.forEach(val => {
                    // tslint:disable-next-line:no-bitwise
                    if ((obj & val.value) == val.value) {
                        temp.push(val.value);
                    }
                });
                this.value = temp;
            } else {
                this.value = obj.split(this.valueSeparator);
            }
        } else {
            this.value = [];
        }
    }

    private onTouched: () => void = () => { };
    private onChange: (val: any) => void = () => { };
    public registerOnChange(fn: any): void { this.onChange = fn; }
    public registerOnTouched(fn: any): void { this.onTouched = fn; }

}