import { acc, IPSDEFormDetail } from '@ibizstudio/api';
import { isNilOrEmpty } from 'qx-util';
import { CreateElement } from 'vue';
import { Vue, Component, Prop, Watch } from 'vue-property-decorator';
import { DesignDefaultContext } from '../../entities';
import { getFormItemIcon } from '../../utils';
import './design-structure-tree.less';

/**
 * 设计结构树
 *
 * @export
 * @class DesignStructureTree
 * @extends {Vue}
 */
@Component({})
export class DesignStructureTree extends Vue {
    /**
     * 设计上下文
     *
     * @type {DesignContext}
     * @memberof DesignStructureTree
     */
    @Prop()
    ctx!: DesignDefaultContext;

    /**
     * 数据集接口
     *
     * @type {string}
     * @memberof DesignStructureTree
     */
    @Prop({ default: 'FetchDefault' })
    datasetInterface!: string;

    /**
     * 是否是表单设计
     *
     * @type {string}
     * @memberof DesignStructureTree
     */
    @Prop({ default: false })
    isFormDesign!: boolean;

    @Prop()
    searchValue = '';

    @Watch('searchValue')
    searchValueChange(val: any) {
        const tree: any = this.$refs.tree;
        tree?.filter(val);
    }

    /**
     * 树数据
     *
     * @type {any[]}
     * @memberof DesignStructureTree
     */
    items: any[] = [];

    /**
     * 当前选中节点
     *
     * @type {*}
     * @memberof DesignStructureTree
     */
    selectNodeData: any;

    /**
     * 树组件ref
     *
     * @type {*}
     * @memberof DesignStructureTree
     */
    tree: any;

    subs: string[] = [];

    created(): void {
        this.nodeSelect = this.nodeSelect.bind(this);
        this.masterLoaded = this.masterLoaded.bind(this);
        this.ctx.evt.on('loaded', this.masterLoaded);
        this.ctx.ctrl.select.evt.on('change', this.selectChange);
        this.subs.push(
            ...acc.commandLocals(
                () => {
                    this.load();
                },
                ['update', 'create', 'remove'],
                this.ctx.ctrl.itemEntity.codeName.toUpperCase(),
            ),
        );
    }

    mounted(): void {
        this.tree = this.$refs.tree;
    }

    destroyed(): void {
        this.ctx.evt.off('loaded', this.masterLoaded);
        this.ctx.ctrl.select.evt.off('change', this.selectChange);
        this.subs.forEach(str => {
            acc.unsubscribeLocal(str);
        });
    }

    /**
     * 选中数据变更
     *
     * @param {*} data
     * @memberof DesignStructureTree
     */
    selectChange(data: any): void {
        if (!this.tree.getNode(data.srfkey)) {
            return;
        }
        this.selectNodeData = this.generateTreeNode(data);
        this.tree.setCurrentKey(data.srfkey);
    }

    /**
     * 主数据加载完毕
     *
     * @memberof DesignStructureTree
     */
    masterLoaded(): void {
        this.load();
    }

    /**
     * 加载数据
     *
     * @return {*}  {Promise<void>}
     * @memberof DesignStructureTree
     */
    async load(): Promise<void> {
        const { ctrl } = this.ctx;
        const s: any = await ctrl.itemService;
        if (s && s[this.datasetInterface]) {
            const res = await s[this.datasetInterface](this.ctx.context);
            if (res.ok) {
                this.formatData(res.data);
                const { select } = ctrl;
                if (select.data) {
                    this.$nextTick(() => {
                        this.selectChange(select.data);
                    });
                }
            }
        } else {
            console.warn(`指定数据集接口「${this.datasetInterface}」不存在!`);
        }
    }

    /**
     * 格式化数据
     *
     * @param {any[]} items
     * @memberof DesignStructureTree
     */
    formatData(items: any[]): void {
        this.items = [];
        items.forEach((item: any) => {
            // 表单看是否是表单分页，别的看srfpkey
            if (this.isFormDesign ? item.itemtype == "FORMPAGE" : isNilOrEmpty(item.srfpkey)) {
                const node = this.generateTreeNode(item);
                this.calcTreeLevel(node, items);
                this.items.push(node);
            }
        });
    }

    /**
     * 计算树层级
     *
     * @param {any} node
     * @param {any[]} items
     * @memberof DesignStructureTree
     */
    calcTreeLevel(node: any, items: any[]): void {
        node.children = items
            .filter((item: any) => item.srfpkey === node.id)
            .map((item: any) => {
                const childNode = this.generateTreeNode(item);
                this.calcTreeLevel(childNode, items);
                return childNode;
            });
    }

    /**
     * 生成树节点数据
     *
     * @param {*} data
     * @return {*}  {*}
     * @memberof DesignStructureTree
     */
    generateTreeNode(data: any): any {
        return {
            text: data.text,
            id: data.srfkey,
            data: data,
        };
    }

    filterTreeNode(value: any, data: any, node: any) {
        if (value) {
            const regExp = value
                .trimStart()
                .trimEnd()
                .toLowerCase();
            const text = data.text.toLowerCase();
            if (text.indexOf(regExp) >= 0) {
                return true;
            } else {
                return false;
            }
        } else {
            return true;
        }
    }

    /**
     * 树选中
     *
     * @param {*} data
     * @param {*} node
     * @memberof DesignStructureTree
     */
    nodeSelect(data: any, _node: any): void {
        this.ctx.ctrl.select.set(data.data);
    }

    /**
     * @description 判断节点是否可拖拽
     * @param {*} node
     * @return {*}  {boolean}
     * @memberof DesignStructureTree
     */
    allowDrag(node: any): boolean {
        if (node.level === 0 || Object.is(node.data.data.detailtype, 'FORMPAGE')) {
            return false;
        }
        return true;
    }

    /**
     * @description 是否可放置
     * @param {*} draggingNode
     * @param {*} dropNode
     * @param {*} type
     * @return {*}  {boolean}
     * @memberof DesignStructureTree
     */
    allowDrop(draggingNode: any, dropNode: any, type: any): boolean {
      if (Object.is(type, 'inner')) {
            if (Object.is(dropNode.data.data.detailtype, 'GROUPPANEL') || Object.is(dropNode.data.data.detailtype, 'FORMPAGE') || Object.is(dropNode.data.data.pvparttype, 'CONTAINER')) {
                return true;
            }
            return false;
        } else {
            if (dropNode.level === 0) {
                return false;
            }
            if (Object.is(dropNode.data.data.detailtype, 'FORMPAGE') && !Object.is(draggingNode.data.data.detailtype, 'FORMPAGE')) {
              return false;
            }
            return true;
        }
    }

    /**
     * @description 树节点拖拽
     * @param {*} before
     * @param {*} after
     * @param {*} inner
     * @param {*} event
     * @memberof DesignStructureTree
     */
    async treeNodeChange(before: any, after: any, inner: any, event: any) {
        const beforeData: any = before.data.data;
        const afterData: any = after.data.data;
        let parent = after.parent.data.data;
        if (afterData.srfdename == 'PSAPPPVPART') {
          beforeData.ppsapppvpartid = afterData.ppsapppvpartid || null;
          beforeData.ppsapppvpartname = afterData.ppsapppvpartname || null;
          if (inner === 'inner') {
              parent = after.data.data;
              beforeData.ppsapppvpartid = afterData.psapppvpartid || null;
              beforeData.ppsapppvpartname = afterData.psapppvpartname || null;
          }
        } else {
          beforeData.ppsdeformdetailid = afterData.ppsdeformdetailid || null;
          beforeData.ppsdeformdetailname = afterData.ppsdeformdetailname || null;
          if (inner === 'inner') {
              parent = after.data.data;
              beforeData.ppsdeformdetailid = afterData.psdeformdetailid || null;
              beforeData.ppsdeformdetailname = afterData.psdeformdetailname || null;
          }
        }
        const srfpkey = parent ? parent.srfkey : null;
        const items: any[] = await this.ctx.ctrl.itemService.selectLocal(this.ctx.context, {
            srfpkey,
        });
        const index = items.findIndex((item: any) => {
            if (afterData.srfdename == 'PSAPPPVPART') {
              return Object.is(item.psapppvpartid, beforeData.psapppvpartid)
            }
            return Object.is(item.psdeformdetailid, beforeData.psdeformdetailid);
        });
        if (!Object.is(index, -1)) {
            const beforeIndex: number = items.findIndex((item: any) => {
              if (afterData.srfdename == 'PSAPPPVPART') {
                return Object.is(item.psapppvpartid, beforeData.psapppvpartid)
              }
              return Object.is(item.psdeformdetailid, beforeData.psdeformdetailid);
            }) || 0;
            items.splice(beforeIndex, 1);
        }
        const afterIndex: number =
        items.findIndex((item: any) => {
          if (afterData.srfdename == 'PSAPPPVPART') {
            return Object.is(item.psapppvpartid, afterData.psapppvpartid)
          }
          return Object.is(item.psdeformdetailid, afterData.psdeformdetailid)
        }) || 0;
        items.splice(Object.is(inner, 'before') ? afterIndex : afterIndex + 1, 0, beforeData);
        this.ctx.ctrl.itemService.disableAcc();
        for (let i = 0; i < items.length; i++) {
            items[i].ordervalue = (i + 1) * 100;
            await this.ctx.ctrl.itemService.UpdateTemp(this.ctx.context, items[i]);
        }
        this.ctx.ctrl.itemService.enableAcc();
        this.$emit('update-order');
    }

    /**
     * 绘制树节点
     *
     * @param {CreateElement} _h
     * @param {*} context
     * @memberof LogicTree
     */
    renderTreeItem(_h: CreateElement, context: any) {
        const { data } = context;
        return (
          <div class={['design-structure-tree-item', this.isFormDesign ? 'form-design-tree-item' : '']}>
            {this.isFormDesign ? this.getTreeNodeIcon(data?.data) : null}
            <div class='text'>{data?.text}</div>
          </div>
        );
    }

    /**
     * 获取树节点对应icon图标
     *
     * @author zhanghengfeng
     * @date 2023-03-28 11:03:24
     * @param {IPSDEFormDetail} data
     * @return {*}
     */
    getTreeNodeIcon(data: IPSDEFormDetail) {
        if (!data || !data.itemtype) {
          return null;
        }
        const type = data.itemtype;
        switch (type) {
          case 'FORMPAGE':
          case 'TABPANEL':
            return <i class='iconfont icon-tab'></i>;
          case 'GROUPPANEL':
            return <i class='iconfont icon-group'></i>;
          case 'RAWITEM':
            return this.getRawItemIcon(data);
          case 'BUTTON':
            return <i class='iconfont icon-button'></i>;
          case 'IFRAME':
            return <i class='iconfont icon-iframe'></i>;
          case 'FORMITEMEX':
            return <i class='iconfont icon-link'></i>;
          case 'DRUIPART':
            return <i class='iconfont icon-drpart'></i>;
          case 'MDCTRL':
            return <i class='iconfont icon-drpart'></i>;
          case 'FORMITEM':
            return <i class={getFormItemIcon(data)}></i>;
          default:
            return null;
        }
    }

    /**
     * 获取数据itemtype属性值为RAWITEM的icon图标
     *
     * @author zhanghengfeng
     * @date 2023-03-28 11:03:54
     * @param {IPSDEFormDetail} data
     * @return {*}
     */
    getRawItemIcon(data: IPSDEFormDetail) {
        if (!data.contenttype) {
          return null;
        }
        const type: string = data.contenttype.toLowerCase();
        const rawItemIcon: Record<string, string> = {
          html: './assets/svg/raw-html.svg',
          image: './assets/svg/raw-image.svg',
          video: './assets/svg/raw-video.svg',
          placeholder: './assets/svg/raw-placeholder.svg',
          divider: './assets/svg/raw-divider.svg',
          info: './assets/svg/raw-info.svg',
          warning: './assets/svg/raw-warning.svg',
          error: './assets/svg/raw-error.svg',
        };
        if (type === 'raw') {
          return <i class='iconfont icon-code'></i>;
        } else if (Object.prototype.hasOwnProperty.call(rawItemIcon, type) && rawItemIcon[type]) {
          return <ion-icon src={rawItemIcon[type]} class='icon'></ion-icon>;
        }
        return null;
    }

    render(h: any): any {
        return (
            <div class='design-structure-tree'>
                {h('el-tree', {
                    ref: 'tree',
                    class: 'design-tree',
                    props: {
                        data: this.items,
                        draggable: true,
                        'allow-drag': this.allowDrag,
                        'allow-drop': this.allowDrop,
                        'node-key': 'id',
                        'highlight-current': true,
                        'default-expand-all': true,
                        'expand-on-click-node': false,
                        'auto-expand-parent	': false,
                        indent: 8,
                        'render-content': this.renderTreeItem,
                        'filter-node-method': this.filterTreeNode,
                    },
                    on: {
                        'current-change': this.nodeSelect,
                        'node-drop': this.treeNodeChange,
                    },
                })}
            </div>
        );
    }
}
