import { OrgDepartmentItem, OrgMemberItem, sdkService } from "@/api/sdk-service";
import Vue from "vue";

export interface OrgMemberItem2Map extends OrgMemberItem {
    empid: string;
    depNames: string[];
    depIds: string[];
}

class EmpTreeController {
    private tree: OrgDepartmentItem[] = [];
    private pdid2Members: { [key: string]: OrgMemberItem2Map[] } = {}
    private roleList: OrgMemberItem2Map[] = [];
    private roleMap4PeidOrEid: { [key: string]: OrgMemberItem2Map } = {}
    private success = false
    private busy = false;
    private action: any[] = [];

    initTree(vue?: Vue) {
        vue && vue.$once("hook:beforeDestroy", () => {
            this.tree = [];
            this.pdid2Members = {};
            this.roleList = [];
            this.roleMap4PeidOrEid = {};
            this.success = false;
            this.busy = false;
            this.action = [];
        });
        this.busy = true;
        return new Promise((resolve, reject) => {
            sdkService.getOrgTree().then((r) => {
                this.tree = r;
                this.success = true;
                this.handlerAction();
                this.filterData2Use(this.tree);
                resolve(JSON.parse(JSON.stringify(this.tree)));
            }).catch((err) => {
                reject(err);
            }).finally(() => {
                this.busy = false;
            });
        });
    }

    getTree() {
        if (this.success) {
            return Promise.resolve(this.tree);
        }
        if (this.busy) {
            return new Promise((resolve) => {
                this.action.push(() => {
                    resolve(this.tree);
                });
            });
        }
        return this.initTree();
    }

    handlerAction() {
        for (let i = 0; i < this.action.length; i++) {
            this.action[i]();
        }
        this.action = [];
    }

    filterData2Use(tree: OrgDepartmentItem[]) {
        if (tree) {
            this.pdid2Members = {};
            this.buildPdid2Members(tree[0], "", "", true);
            this.roleList = [];
            Object.keys(this.pdid2Members).forEach((i) => {
                this.roleList = this.roleList.concat(
                    this.pdid2Members[i]
                );
            });
            this.roleList.forEach(i => {
                const val = JSON.parse(JSON.stringify(i));
                this.roleMap4PeidOrEid[i.peid] = val;
                this.roleMap4PeidOrEid[i.id] = val;
            });
        }
    }

    getRoleMap4PeidOrEid() {
        return JSON.parse(JSON.stringify(this.roleMap4PeidOrEid));
    }

    getRoleList() {
        return JSON.parse(JSON.stringify(this.roleList)) as OrgMemberItem2Map[];
    }

    getPdid2Members() {
        return JSON.parse(JSON.stringify(this.pdid2Members));
    }

    transitionPid2Id(pidOrId: string) {
        return this.roleMap4PeidOrEid[pidOrId].id;
    }

    buildPdid2Members(tree: OrgDepartmentItem | OrgMemberItem, depName = "", depId = "", root = false) {
        const pTree: OrgDepartmentItem | null = tree as OrgDepartmentItem;
        const mTree: OrgMemberItem | null = tree as OrgMemberItem;
        if (pTree && pTree.pdid) {
            this.pdid2Members[pTree.pdid] =
                this.pdid2Members[pTree.pdid] || [];
            const chilren = pTree.children;
            if (!chilren || !chilren.length) {
                return {
                    _last: true,
                };
            }
            let users: OrgMemberItem2Map[] = [];
            for (let i = 0; i < chilren.length; i++) {
                const user = this.buildPdid2Members(chilren[i],
                    root ? "" : pTree.name,
                    root ? "" : pTree.pdid);
                if (user._last) {
                    continue;
                }
                if (user._isPid) {
                    users = users.concat(user._isPid);
                    continue;
                }
                if (user._none) {
                    continue;
                }
                users.push(user);
            }
            this.pdid2Members[pTree.pdid] = this.quchong(
                this.pdid2Members[pTree.pdid].concat(users)
            );

            return {
                _isPid: JSON.parse(
                    JSON.stringify(this.pdid2Members[pTree.pdid])
                ),
            };
        } else {
            Object.assign(tree, {
                empid: mTree.peid,
                depNames: depName ? [depName] : [],
                depIds: depId ? [depId] : [],
            });
            if ([0, 1, "0", "1"].includes(mTree.enable)) {
                return JSON.parse(JSON.stringify(tree));
            }
            return {
                _none: true,
            };
        }
    }

    quchong(arr: OrgMemberItem2Map[]) {
        const result = [];
        const obj: { [key: string]: boolean } = {};
        const objIndex: { [key: string]: number } = {};
        for (let i = 0; i < arr.length; i++) {
            if (!obj[arr[i].id]) {
                result.push(arr[i]);
                obj[arr[i].id] = true;
                objIndex[arr[i].id] = result.length - 1;
            } else {
                let val = result[objIndex[arr[i].id]].depNames || [];
                val = val.concat(arr[i].depNames);
                result[objIndex[arr[i].id]].depNames = val;

                let val4Id = result[objIndex[arr[i].id]].depIds || [];
                val4Id = val4Id.concat(arr[i].depIds);
                result[objIndex[arr[i].id]].depIds = val4Id;
            }
        }
        return result;
    }
}

const empTreeController = new EmpTreeController();
export { empTreeController };