import { Vue, Component, Prop } from 'vue-property-decorator';
import { IDesignContext } from '../../interface';
import { isEmpty, isNil } from 'ramda';
import { IEntity } from '@ibizstudio/api';
import { CreateElement } from 'vue';
import { getControl, IPSAppDataEntity, IPSAppDEEditView, IPSDEEditForm } from '@ibizstudio-ex/runtime';

/**
 * 属性表单呈现容器
 *
 * @export
 * @class PropertyFormContainer
 * @extends {Vue}
 */
@Component({})
export class PropertyFormContainer extends Vue {
    /**
     * 设计上下文
     *
     * @type {IDesignContext}
     * @memberof PropertyFormContainer
     */
    @Prop()
    ctx!: IDesignContext;

    /**
     * 视图模型实例
     *
     * @type {*}
     * @memberof PropertyFormContainer
     */
    @Prop()
    viewModel!: IPSAppDEEditView;

    /**
     * 当前激活部件
     *
     * @type {{}}
     * @memberof PropertyFormContainer
     */
    activateControl: { key?: string; ctrl?: IPSDEEditForm; srfkey?: string; entity?: IPSAppDataEntity } = {};

    /**
     * 当前选中数据
     *
     * @type {*}
     * @memberof PropertyFormContainer
     */
    selectData: any = null;

    /**
     * 选中上下文
     *
     * @author chitanda
     * @date 2022-11-23 12:11:10
     * @type {(IContext | null)}
     */
    selectContext: IContext | null = null;

    created(): void {
        this.selectChange = this.selectChange.bind(this);
        this.reload = this.reload.bind(this);
        const { select } = this.ctx.ctrl;
        select.evt.on('change', this.selectChange);
        this.ctx.evt.on('reload', this.reload);
        if (select.data) {
            this.selectChange(select.data);
        }
    }

    /**
     * 重新加载
     *
     * @memberof PropertyFormContainer
     */
    reload() {
        this.selectChange(this.ctx.ctrl.select.data);
    }

    /**
     * 实例销毁前
     *
     * @memberof PropertyFormContainer
     */
    destroyed(): void {
        this.ctx.evt.off('reload', this.reload);
        this.ctx.ctrl.select.evt.off('change', this.selectChange);
    }

    /**
     * 选中数据变更
     *
     * @author chitanda
     * @date 2022-11-23 12:11:38
     * @param {IEntity} [data]
     * @return {*}  {Promise<void>}
     */
    async selectChange(data?: IEntity): Promise<void> {
        const { context } = this.ctx.ctrl.select;
        if (context) {
          this.selectContext = context;
        }
        if (isNil(data) || isEmpty(data)) {
            this.selectData = {};
            this.activateControl = {};
            this.$forceUpdate();
        } else {
            this.selectData = data;
            const ctrlModel = getControl(this.viewModel, data.itemtype, true) as IPSDEEditForm;
            if (ctrlModel) {
                const ctrlName = ctrlModel?.name.toLowerCase();
                this.activateControl = {
                    key: ctrlName,
                    ctrl: ctrlModel,
                    srfkey: data?.srfkey,
                    entity: (await ctrlModel.getPSAppDataEntity()!.fill()!) as IPSAppDataEntity,
                };
                this.$forceUpdate();
                if (ctrlModel) {
                    this.$nextTick(() => {
                        this.formLoad(ctrlName!, {});
                    });
                }
            }
        }
    }

    /**
     * 表单加载数据
     *
     * @param {string} tag
     * @param {*} data
     * @param {number} [count=0]
     * @return {*}  {void}
     * @memberof PropertyFormContainer
     */
    formLoad(tag: string, data: any, count = 0): void {
        if (count > 100) {
            return;
        }
        count++;
        setTimeout(() => {
            const ref: any = this.$refs[tag];
            if (ref?.ctrl?.controlIsLoaded == true) {
                ref.ctrl.load(data);
            } else {
                this.formLoad(tag, data, count);
            }
        }, 50);
    }

    /**
     * 绘制函数
     *
     * @param {CreateElement} h
     * @memberof PropertyFormContainer
     */
    render(h: CreateElement) {
        if (!this.activateControl.ctrl || !this.viewModel) {
            return null;
        }
        const dynamicProps = {
            context: {
                ...this.ctx.context,
                ...this.selectContext,
                [this.activateControl.entity!.codeName.toLowerCase()]: this.activateControl.srfkey,
            },
            designCtx: { ...this.ctx },
        };
        const staticProps: any = {};
        Object.defineProperty(staticProps, 'modelData', {
            enumerable: false,
            value: this.activateControl.ctrl,
        });
        return h('app-control-shell', {
            staticClass: this.activateControl.key,
            props: {
                staticProps,
                dynamicProps,
            },
            key: this.activateControl.key,
            ref: this.activateControl.key,
        });
    }
}
