import {
    Menu,
    app,
    dialog,
    BrowserWindow,
    MenuItem,
    WebContents,
    MenuItemConstructorOptions,
} from "electron";
import * as fs from "fs";
import * as Utils from "../common/Utils";
import MainEventType from "../common/MainEventType";
import { MainProcess } from "./MainProcess";
import Settings from "./Settings";

const packageConf = require("../package.json");

export default class AppMenu {
    private mainProcess: MainProcess;
    private mainWindow: BrowserWindow;
    private webContents: WebContents;
    private settings: Settings;

    constructor(mainProcess: MainProcess) {
        this.mainProcess = mainProcess;
        this.mainWindow = mainProcess.mainWindow;
        this.webContents = mainProcess.mainWindow.webContents;
        this.settings = mainProcess.settings;
    }

    createMenu() {
        const menu: Menu = new Menu();
        menu.append(this.createFileMenu());
        menu.append(this.createEditMenu());
        menu.append(this.createNodeMenu());
        menu.append(this.createWorkspaceMenu());
        menu.append(this.createToolsMenu());
        return menu;
    }

    private createFileMenu() {
        const fileItems: MenuItemConstructorOptions[] = [];
        for (let path of this.settings.recentFiles) {
            fileItems.push({
                label: path,
                click: () => {
                    console.log("open recent file", path);
                },
            });
        }

        return new MenuItem({
            label: "行为树",
            submenu: [
                {
                    label: "新建",
                    accelerator: "ctrl+n",
                    click: () => {
                        (async () => {
                            const res = await dialog.showSaveDialog({
                                properties: ["showOverwriteConfirmation"],
                                filters: [{ name: "Json", extensions: ["json"] }],
                            });
                            if (!res.canceled) {
                                const path = res.filePath;
                                fs.writeFileSync(
                                    path,
                                    JSON.stringify(Utils.createNewTree(path), null, 2)
                                );
                                this.webContents.send(MainEventType.CREATE_TREE, path);
                            }
                        })();
                    },
                },
                {
                    label: "打开文件",
                    accelerator: "Ctrl+O",
                    click: () => {
                        (async () => {
                            const res = await dialog.showOpenDialog({
                                properties: ["openFile"],
                                filters: [{ name: "Json", extensions: ["json"] }],
                            });
                            if (res.filePaths.length > 0) {
                                const path = res.filePaths[0];
                                if (this.settings.recentFiles.indexOf(path) < 0) {
                                    this.settings.recentFiles.unshift(path);
                                    this.settings.save();
                                    this.mainProcess.rebuildMenu();
                                }
                                this.webContents.send(MainEventType.OPEN_FILE, path);
                            }
                        })();
                    },
                },
                { type: "separator" },
                {
                    label: "最近打开",
                    submenu: fileItems,
                },

                { type: "separator" },
                {
                    label: "保存",
                    accelerator: "ctrl+s",
                    click: () => {
                        this.webContents.send(MainEventType.SAVE);
                    },
                },
                {
                    label: "全部保存",
                    accelerator: "ctrl+shift+s",
                    click: () => {
                        this.webContents.send(MainEventType.SAVE_ALL);
                    },
                },
                {
                    label: "合并导出Json",
                    click: () => {
                        (async () => {
                            const res = await dialog.showSaveDialog({
                                properties: ["showOverwriteConfirmation"],
                                filters: [{ name: "Json", extensions: ["json"] }],
                            });
                            if (res.filePath) {
                                const curWorkspace = this.settings.curWorkspace;
                                curWorkspace.writeAllTrees(res.filePath, (err) => {
                                    const msg = err ? err : "导出成功";
                                    dialog.showMessageBox({
                                        type: "info",
                                        buttons: ["ok"],
                                        message: msg,
                                    });
                                });
                            }
                        })();
                    },
                },
            ],
        });
    }

    private createEditMenu() {
        return new MenuItem({
            label: "编辑",
            submenu: [
                {
                    label: "撤销",
                    accelerator: "ctrl+z",
                    click: () => {
                        this.webContents.send(MainEventType.UNDO);
                    }
                },
                {
                    label: "恢复",
                    accelerator: "ctrl+y",
                    click: () => {
                        this.webContents.send(MainEventType.REDO);
                    }
                },
                { type: "separator" },
                {
                    label: "新建节点",
                    accelerator: "insert",
                    click: () => {
                        this.webContents.send(MainEventType.CREATE_NODE, "unknow");
                    },
                },
                {
                    label: "删除节点",
                    accelerator: "delete",
                    click: () => {
                        this.webContents.send(MainEventType.DELETE_NODE);
                    },
                },
                { type: "separator" },
                {
                    label: "复制节点",
                    accelerator: "ctrl+c",
                    role: "copy",
                    click: () => {
                        this.webContents.send(MainEventType.COPY_NODE);
                    },
                },
                {
                    label: "粘贴节点",
                    accelerator: "ctrl+v",
                    click: () => {
                        this.webContents.send(MainEventType.PASTE_NODE);
                    },
                },
            ]
        })
    }

    private createWorkspaceMenu() {
        const openWorkspace = (path: string) => {
            const curWorkspace = this.settings.curWorkspace;
            curWorkspace.setFilepath(path);
            curWorkspace.load();
            this.settings.pushRecentWorkspace(path);
            this.mainProcess.rebuildMenu();
            this.webContents.send(
                MainEventType.OPEN_DIR,
                curWorkspace.getWorkdir(),
                curWorkspace.getFilepath()
            );
        };
        const saveToNewPath = () => {
            (async () => {
                const res = await dialog.showSaveDialog({
                    properties: ["showOverwriteConfirmation"],
                    filters: [{ name: "Json", extensions: ["json"] }],
                });
                if (!res.canceled) {
                    this.settings.curWorkspace.setFilepath(res.filePath);
                    this.settings.curWorkspace.save();
                    openWorkspace(res.filePath);
                }
            })();
        };
        const recentItems: MenuItemConstructorOptions[] = [];
        for (let path of this.settings.recentWorkspaces) {
            recentItems.push({
                label: path,
                click: () => {
                    console.log("open recent workspace", path);
                    openWorkspace(path);
                },
            });
        }
        return new MenuItem({
            label: "工作区",
            submenu: [
                {
                    label: "打开",
                    click: () => {
                        (async () => {
                            const res = await dialog.showOpenDialog({
                                properties: ["openFile"],
                                filters: [{ name: "Json", extensions: ["json"] }],
                            });
                            if (res.filePaths.length > 0) {
                                openWorkspace(res.filePaths[0]);
                            }
                        })();
                    },
                },
                {
                    label: "保存",
                    click: () => {
                        if (this.settings.curWorkspace.getFilepath()) {
                            this.settings.curWorkspace.save();
                        } else {
                            saveToNewPath();
                        }
                    },
                },
                {
                    label: "另存为",
                    click: () => {
                        saveToNewPath();
                    },
                },
                {
                    label: "刷新",
                    accelerator: "F5",
                    click: () => {
                        console.log("reload workspace");
                        openWorkspace(this.settings.curWorkspace.getFilepath());
                    },
                },
                {
                    label: "最近打开",
                    submenu: recentItems,
                },
                { type: "separator" },
                {
                    label: "打开目录",
                    accelerator: "Ctrl+Shift+O",
                    click: () => {
                        if (!this.settings.curWorkspace.getNodeConfPath()) {
                            dialog.showErrorBox("警告", "请先指定节点定义配置!");
                            return;
                        }
                        (async () => {
                            const res = await dialog.showOpenDialog({
                                properties: ["openDirectory"],
                            });
                            if (res.filePaths.length > 0) {
                                const curWorkspace = this.settings.curWorkspace;
                                const path = res.filePaths[0];
                                curWorkspace.setWorkdir(path);
                                curWorkspace.save();
                                this.webContents.send(
                                    MainEventType.OPEN_DIR,
                                    path,
                                    curWorkspace.getFilepath()
                                );
                            }
                        })();
                    },
                },
                {
                    label: "节点定义",
                    submenu: [
                        {
                            label: "选择文件",
                            click: () => {
                                (async () => {
                                    const res = await dialog.showOpenDialog({
                                        properties: ["openFile"],
                                        filters: [{ name: "Json", extensions: ["json"] }],
                                    });
                                    if (res.filePaths.length > 0) {
                                        const nodeConfigPath = res.filePaths[0];
                                        this.settings.curWorkspace.setNodeConfPath(nodeConfigPath);
                                        this.mainProcess.rebuildMenu();
                                    }
                                })();
                            },
                        },
                        { type: "separator" },
                        { label: this.settings.nodeConfPath },
                    ],
                },
                { type: "separator" },
                {
                    label: "关闭",
                    click: () => {
                        app.quit();
                    },
                },
            ],
        });
    }

    private createToolsMenu() {
        const serverItems: MenuItemConstructorOptions[] = [];
        const curServerName = this.settings.serverName;
        for (let model of this.settings.curWorkspace.getServers()) {
            serverItems.push({
                label: `${model.name} ${model.host}`,
                type: 'checkbox',
                checked: curServerName == model.name,
                click: () => {
                    this.settings.serverName = model.name;
                    this.mainProcess.rebuildMenu();
                }
            })
        }
        return new MenuItem({
            label: "开发工具",
            submenu: [
                {
                    label: "热更",
                    accelerator: "Ctrl+R",
                    click: () => {
                        this.webContents.send(MainEventType.RELOAD_SERVER);
                    }
                },
                {
                    label: "联调服务器",
                    submenu: serverItems,
                },
                {
                    label: "批处理脚本",
                    click: () => {
                        (async () => {
                            const res = await dialog.showOpenDialog({
                                properties: ["openFile"],
                                filters: [{ name: "Javascript", extensions: ["js"] }],
                            });
                            if (res.filePaths.length > 0) {
                                this.webContents.send(MainEventType.BATCH_EXEC, res.filePaths[0]);
                            }
                        })();
                    }
                },
                {
                    type: 'separator',
                },
                {
                    label: "打开控制台",
                    accelerator: "Ctrl+Shift+I",
                    click: (_, browserWindow) => {
                        browserWindow.webContents.toggleDevTools();
                    },
                },
                {
                    label: "重载编辑器",
                    click: (_, browserWindow) => {
                        browserWindow.reload();
                    },
                },
                {
                    type: 'separator',
                },
                {
                    label: `当前版本：${packageConf.version}`
                }
            ],
        });
    }

    private createNodeMenu() {
        const classifyItems: MenuItemConstructorOptions[] = [];
        const map: { [key: string]: MenuItemConstructorOptions } = {};
        for (let t of this.settings.nodeClassify) {
            let item: MenuItemConstructorOptions = {
                id: t.classify,
                label: `${t.classify}(${t.desc})`,
                submenu: [],
            };
            classifyItems.push(item);
            map[t.classify] = item;
        }
        const other: MenuItemConstructorOptions = {
            id: "other",
            label: "其它",
            submenu: [],
        };
        var hasOther = false;

        for (let node of this.settings.nodeConfig) {
            const item: MenuItemConstructorOptions = {
                label: `${node.name}(${node.desc})`,
                click: () => {
                    console.log("create node", node.name);
                    this.webContents.send(MainEventType.CREATE_NODE, node.name);
                },
            };
            let typeItem = map[node.type];
            if (!typeItem) {
                typeItem = other;
                hasOther = true;
            }
            if (typeItem.submenu instanceof Menu) {
                console.log("typeItem.submenu error", typeItem);
            } else {
                typeItem.submenu.push(item);
            }
        }

        if (hasOther) {
            classifyItems.push(other);
        }

        return new MenuItem({
            label: "新建节点",
            submenu: classifyItems,
        });
    }
}
