<template>
    <div class="app-common-microcom">
        <template v-if="multiple" class="app-common-microcom-multiple">
            <checkbox-group v-model="selectArray" @on-change="selectChange">
                <checkbox v-for="(item,index) in datas" :key="index" :label="item.id" :disabled="disabled || item.disabled || readonly">
                    <span>{{item.label}}{{item.mdeptname ? `（${item.mdeptname}）` : ''}}</span>
                </checkbox>
            </checkbox-group>
        </template>
        <template v-else class="app-common-microcom-radio">
            <el-radio-group v-model="selectArray[0]">
                <el-radio v-for="(item,index) in datas" :key="index" :label="item.id" :disabled="disabled || item.disabled || readonly" @change="selectChange(item)">
                    {{ item.label }}{{item.mdeptname ? `（${item.mdeptname}）` : ''}}
                </el-radio>
            </el-radio-group>
        </template>
    </div>
</template>

<script lang="ts">
import { Vue, Component, Prop, Watch } from "vue-property-decorator";
import { LogUtil  } from 'ibiz-core';
import axios from 'axios';
import { Subject, Subscription } from "rxjs";

@Component({})
export default class AppCommonMicrocom extends Vue {

    /**
     * 数据接口地址
     * 
     * @type {string}
     * @memberof AppCommonMicrocom 
     */
    @Prop()
    public url!: string;

    /**
     * 填充属性
     * 
     * @type {*}
     * @memberof AppCommonMicrocom
     */
    @Prop()
    public fillMap!: any;

    /**
     * 关联属性
     * 
     * @type {string}
     * @memberof AppCommonMicrocom
     */
    @Prop()
    public valueitem!: string;

    /**
     * 表单项名称
     * 
     * @type {string}
     * @memberof AppCommonMicrocom
     */
    @Prop()
    public name!: string;

    /**
     * 局部上下文导航参数
     * 
     * @type {any}
     * @memberof AppCheckBox
     */
    @Prop() public localContext!:any;

    /**
     * 局部导航参数
     * 
     * @type {any}
     * @memberof AppCheckBox
     */
    @Prop() public localParam!:any;

    /**
     * 上下文
     * 
     * @type {*}
     * @memberof AppCommonMicrocom
     */
    @Prop()
    public context!: any;

    /**
     * 视图参数
     * 
     * @type {*}
     * @memberof AppCommonMicrocom
     */
    @Prop()
    public viewparams!: any;

    /**
     * 表单数据对象
     * 
     * @type {*}
     * @memberof AppCommonMicrocom
     */
    @Prop()
    public data!: any;

    /**
     * 是否启用
     * 
     * @type {boolean}
     * @memberof AppCommonMicrocom 
     */
    @Prop()
    public disabled?: boolean;

    /**
     * 只读模式
     * 
     * @type {boolean}
     */
    @Prop({default: false})
    public readonly?: boolean;

    /**
     * 是否多选
     *
     * @type {boolean}
     * @memberof AppCommonMicrocom
     */  
    @Prop({default: false})
    public multiple?: boolean;

    /**
     * 地址过滤参数
     *
     * @type {boolean}
     * @memberof AppCommonMicrocom
     */ 
    @Prop()
    public filter!: string;

    /**
     * 请求方式
     *
     * @type {string}
     * @memberof AppCommonMicrocom
     */ 
    @Prop({ default: 'get'})
    public requestMode!: 'get' | 'post' | 'delete' | 'put';

    /**
     * 上下文状态
     *
     * @type {Subject<any>}
     * @memberof AppCommonMicrocom
     */ 
    @Prop()
    public contextState?: Subject<any>;

    /**
     * 选中项集合
     *
     * @type {*}
     * @memberof AppCommonMicrocom
     */  
    public selects: any[] = [];

    /**
     * 数据集合
     *
     * @type {*}
     * @memberof AppCommonMicrocom
     */  
    public datas: any[] = [];

    /**
     * 回显值
     * 
     * @type {*}
     * @memberof AppCommonMicrocom
     */
    public selectArray: any[] = [];

    /**
     * 状态事件
     * 
     * @type {*}
     * @memberof AppCommonMicrocom
     */
    public contextStateEvent: Subscription | undefined;

    /**
     * 值变化
     *
     * @type {*}
     * @memberof AppGroupSelect
     */  
    @Watch('data',{
        immediate:true,
        deep:true
    })
    onValueChange(newVal: any, oldVal: any) {
        this.selects = [];
        if (newVal) {
            let item: any = {};
            item.label = this.data[this.name] ? this.data[this.name].split(',') : [];
            item.id = this.data[this.valueitem] ? this.data[this.valueitem].split(',') : [];
            this.selectArray = item.id;
            if(this.fillMap) {
                for(let key in this.fillMap) {
                    item[this.fillMap[key]] = this.data[key] ? this.data[key].split(',') : [];
                }
            }
            if(item.label.length > 0){
                item.label.forEach((val: string, index: number) => {
                    let _item: any = {};
                    for(let key in item) {
                        _item[key] = item[key][index] ? item[key][index] : null;
                    }
                    this.selects.push(_item);
                })
            }
        }
    }

    /**
     * Vue生命周期 --- Created
     *
     * @type {*}
     * @memberof AppGroupSelect
     */  
    public created() {
        if (this.contextState) {
            this.contextStateEvent = this.contextState.subscribe(({ type, data }: any) => {
                if (type === 'load') {
                    this.load();
                }
            })
        } else {
            this.load();
        }
    }

    /**
     * 处理特殊filter参数
     * 
     * @type {*}
     * @memberof AppCommonMicrocom
     */
    public handleFilterValue(value: string) {
        if (value && value.startsWith('%') && value.endsWith('%')) {
            const key = value.slice(1, value.length - 1);
            if (this.data && this.data.hasOwnProperty(key)) {
                return this.data[key];
            } else if (this.context && this.context[key]) {
                return this.context[key];
            } else if (this.viewparams && this.viewparams[key]) {
                return this.viewparams[key];
            }
        }
        return value;
    }

    /**
     * 解析URL
     * 
     * @type {*}
     * @param context 上下文参数
     * @param viewparams 视图参数
     * @memberof AppCommonMicrocom
     */
    public parseURL(context: any, viewparams: any) {
        let url = this.url;
        const filterArr: Array<any> = this.filter ? this.filter.split('|') : [];
        const urlParm = url.match(/\${(.+?)\}/g);
        if (urlParm) {
            urlParm.forEach((item: string) => {
                const key = item.substring(2, item.length - 1).toLowerCase();
                const res = new RegExp("\\${"+key+"}");
                let value = null;
                const isFilterKey = key.match(/filter/g) ? true : false;
                if (isFilterKey) {
                    const filterIndex = key.slice(6);
                    if (filterIndex) {
                        if (isNaN(parseInt(filterIndex)) || filterArr.length < parseInt(filterIndex) - 1) {
                            LogUtil.warn(this.$t('components.microcom.filterwarn'))
                        } else {
                            value = this.handleFilterValue(filterArr[parseInt(filterIndex) - 1]);
                        }
                    } else {
                        value = filterArr[0];
                    }
                } else {
                    if (this.data && this.data.hasOwnProperty(key)) {
                        value = this.data[key];
                    } else if (context && context[key]) {
                        value = context[key];
                    } else if (viewparams && viewparams[key]) {
                        value = viewparams[key];
                    }
                }
                url = url.replace(res, value);
            })
        }
        return url;
    }

    /**
     * 公共参数处理
     *
     * @param {*} arg
     * @returns
     * @memberof AppCheckBox
     */
    public handlePublicParams(arg: any) {
        // 合并表单参数
        arg.param = this.viewparams ? JSON.parse(JSON.stringify(this.viewparams)) : {};
        arg.context = this.context ? JSON.parse(JSON.stringify(this.context)) : {};
        // 附加参数处理
        if (this.localContext && Object.keys(this.localContext).length >0) {
            let _context = this.$util.computedNavData(this.data,arg.context,arg.param,this.localContext);
            Object.assign(arg.context,_context);
        }
        if (this.localParam && Object.keys(this.localParam).length >0) {
            let _param = this.$util.computedNavData(this.data,arg.param,arg.param,this.localParam);
            Object.assign(arg.param,_param);
        }
    }

    /**
     * 加载数据
     * 
     * @type {*}
     * @memberof AppCommonMicrocom
     */
    public load() {
        let data: any = {};
        this.handlePublicParams(data);
        // 参数处理
        let context = data.context;
        let viewparam = data.param;
        const url = this.parseURL(context, viewparam);
        if(url){
            this.datas = [];
            axios({method: this.requestMode, url: url, params: viewparam}).then((response: any) => {
                if (response && response.status == 200) {
                    if(response.data.length > 0){
                        let item: any;
                        response.data.forEach((_item: any) => {
                            item = _item;
                            if(this.fillMap) {
                                item.label = _item[this.fillMap.label];
                                item.id = _item[this.fillMap.id];
                            } else {
                                item.label = _item[this.name];
                                item.id = _item[this.valueitem];
                            }
                            this.datas.push(item);
                        })
                    }
                }
            }).catch((response: any)=> {
                
            })
        }
    }

    /**
     * 选中数据改变
     * 
     * @type {*}
     * @memberof AppCommonMicrocom
     */
    public selectChange(item: any){
        this.selects = [];
        if(this.multiple){
            if(item){
                item.forEach((_item: any) => {
                    const _data: any = this.datas.find((data: any) => {
                        return Object.is(data.id, _item);
                    })
                    if(_data){
                        this.selects.push(_data);
                    }
                })
            }
        } else {
            this.selects.push(item);
        }
        this.setValue();
    }

    /**
     * 设置值
     *
     * @type {*}
     * @memberof AppCommonMicrocom
     */  
    public setValue() {
        let item: any = {};
        item[this.name] = null;
        if(this.valueitem) {
            item[this.valueitem] = null;
        }
        if(this.fillMap) {
            for(let key in this.fillMap) {
                item[key] = null;
            }
        }
        if(this.multiple) {
            this.selects.forEach((select: any) => {
                item[this.name] = item[this.name] ? `${item[this.name]},${select.label}` : select.label;
                if(this.valueitem) {
                    item[this.valueitem] = item[this.valueitem] ? `${item[this.valueitem]},${select.id}` : select.id;
                }
                if(this.fillMap) {
                    for(let key in this.fillMap) {
                        item[key] = item[key] ? `${item[key]},${select[this.fillMap[key]]}` : select[this.fillMap[key]];
                    }
                }
            });
        } else {
            item[this.name] = this.selects.length > 0 ? this.selects[0].label : null;
            if(this.valueitem) {
                item[this.valueitem] = this.selects.length > 0 ? this.selects[0].id : null;
            }
            if(this.fillMap) {
                for(let key in this.fillMap) {
                    item[key] = this.selects.length > 0 ? this.selects[0][this.fillMap[key]] : null;
                }
            }
        }
        for(let key in item) {
            // 抛出当前表单项与值项
            if (Object.is(key, this.name) || Object.is(key, this.valueitem)) {
                this.$emit('formitemvaluechange', { name: key, value: item[key] });
            }
        }
    }

    /**
     * 组件销毁
     * 
     * @type {*}
     * @memberof AppCommonMicrocom
     */
    public destroyed() {
        if (this.contextStateEvent) {
            this.contextStateEvent.unsubscribe();
        }
    }
}
</script>

<style lang='less'>
@import "./app-common-microcom.less";
</style>