// 定义所需的类
class TreeViewRoot {
    Level: number;
    TradeName: string;
    listNode: TreeViewNode[];

    constructor() {
        this.Level = 0;
        this.TradeName = "";
        this.listNode = [];
    }
}

class TreeViewNode {
    TradeName: string;
    MenuCode: string;
    Action: string;
    listLeaf: TreeViewLeaf[];

    constructor() {
        this.TradeName = "";
        this.MenuCode = "";
        this.Action = "";
        this.listLeaf = [];
    }
}

class TreeViewLeaf {
    TradeName: string;
    MenuCode: string;
    Action: string;

    constructor() {
        this.TradeName = "";
        this.MenuCode = "";
        this.Action = "";
    }
}

class MetaData {
    Key: string;
    Value: string;

    constructor() {
        this.Key = "";
        this.Value = "";
    }
}

class AttachProperty {
    static SetMetaData(leaf: TreeViewLeaf, metaDataList: MetaData[]) {
        // 这里可以实现具体的附加元数据逻辑
    }
}

class TreeViewXmlSource {
    categoryList: TreeViewRoot[];
    listMetaData: MetaData[];
    strPath: string;
    xmlDocument: Document | null;

    constructor() {
        this.categoryList = [];
        this.listMetaData = [];
        this.strPath = `${process.cwd()}/Menu.xml`;
        this.xmlDocument = null;
        this.InitDataTable();
    }

    GetXmlMenu(): TreeViewRoot[] {
        return this.categoryList;
    }

    private InitDataTable() {
        this.nodeListToTable(this.LoadXmlFile(), null, null, null);
    }

    private LoadXmlFile(): NodeListOf<Element> {
        if (this.xmlDocument === null) {
            const xhr = new XMLHttpRequest();
            xhr.open('GET', this.strPath, false);
            xhr.send();
            this.xmlDocument = xhr.responseXML;
        }
        return this.xmlDocument!.querySelectorAll('menu');
    }

    private nodeListToTable(
        nodeList: NodeListOf<Element>,
        TreeViewRoot: TreeViewRoot | null,
        treeViewNode: TreeViewNode | null,
        treeViewLeaf: TreeViewLeaf | null
    ) {
        for (let i = 0; i < nodeList.length; i++) {
            const item = nodeList[i];
            if (item.nodeType !== Node.ELEMENT_NODE) {
                continue;
            }

            try {
                switch (item.localName) {
                    case "menu":
                        if (item.hasChildNodes()) {
                            const nodes = item.childNodes as NodeListOf<Element>;
                            this.nodeListToTable(nodes, null, null, null);
                        }
                        break;
                    case "category":
                        if (item.parentNode != null) {//item.parentNode?.localName === "menu"
                            // TreeViewRoot = new TreeViewRoot();
                            TreeViewRoot.Level = 1;
                            TreeViewRoot.TradeName = this.GetAttribute(item, "name");
                            this.categoryList.push(TreeViewRoot);

                            if (item.hasChildNodes()) {
                                const nodes = item.childNodes as NodeListOf<Element>;
                                TreeViewRoot.listNode = [];
                                this.nodeListToTable(nodes, TreeViewRoot, null, null);
                            }
                        } else {
                            treeViewNode = new TreeViewNode();
                            treeViewNode.TradeName = this.GetAttribute(item, "name");
                            TreeViewRoot!.listNode.push(treeViewNode);

                            if (item.hasChildNodes()) {
                                const nodes = item.childNodes as NodeListOf<Element>;
                                treeViewNode.listLeaf = [];
                                this.nodeListToTable(nodes, TreeViewRoot, treeViewNode, null);
                            }
                        }
                        break;
                    case "abstractcategory":
                        //TreeViewRoot = new TreeViewRoot();
                        TreeViewRoot.Level = 1;
                        TreeViewRoot.TradeName = "";
                        this.categoryList.push(TreeViewRoot);

                        if (item.hasChildNodes()) {
                            const nodes = item.childNodes as NodeListOf<Element>;
                            TreeViewRoot.listNode = [];
                            this.nodeListToTable(nodes, TreeViewRoot, null, null);
                        }
                        break;
                    case "trade":
                        if (item.parentNode?.parentNode?.localName === "menu") {
                            treeViewNode = new TreeViewNode();
                            treeViewNode.TradeName = this.GetAttribute(item, "name");
                            treeViewNode.MenuCode = this.GetAttribute(item, "menucode");
                            treeViewNode.Action = this.GetAttribute(item, "action");
                            TreeViewRoot!.listNode.push(treeViewNode);
                        } else {
                            treeViewLeaf = new TreeViewLeaf();
                            treeViewLeaf.TradeName = this.GetAttribute(item, "name");
                            treeViewLeaf.MenuCode = this.GetAttribute(item, "menucode");
                            treeViewLeaf.Action = this.GetAttribute(item, "action");
                            treeViewNode!.listLeaf.push(treeViewLeaf);

                            if (item.hasChildNodes()) {
                                const nodes = item.childNodes as NodeListOf<Element>;
                                this.listMetaData = [];
                                this.nodeListToTable(nodes, null, null, treeViewLeaf);
                            }
                        }
                        break;
                    case "MetaDatadata":
                        const metaData = new MetaData();
                        metaData.Key = this.GetAttribute(item, "key");
                        metaData.Value = this.GetAttribute(item, "value");
                        this.listMetaData.push(metaData);
                        AttachProperty.SetMetaData(treeViewLeaf!, this.listMetaData);
                        break;
                }
            } catch (ex) {
                const error = item.localName;
            }
        }
    }

    private GetAttribute(node: Element, attName: string): string {
        const attr = node.getAttribute(attName);
        return attr ? attr : "";
    }
}

export default TreeViewXmlSource;
