const {
    app,
    BrowserWindow,
    screen,
    Tray,
    nativeImage,
    Menu,
    ipcMain,
    clipboard,
    dialog,
    crashReporter,
    desktopCapturer,
} = require('electron');
const path = require('node:path')
const updateJs = require('./src/utils/package/update')
const fs = require('fs');
const Registry = require('winreg');
const { autoUpdater, CancellationToken } = require('electron-updater');
const signalR = require('@microsoft/signalr');
const { setTimeout, setInterval, clearTimeout, clearInterval } = require('timers');
const cancellationToken = new CancellationToken()
app.allowRendererProcessReuse = false;
let mainWindow = null;
let childWindow = {}
let isMaximized = false;
let env;
let regKey;
let connection = null;
let envStr;
let startNumber = 0;

class AppWindow extends BrowserWindow {
    constructor(config) {
        const basicConfig = {
            webPreferences: {
                contextIsolation: false,
                nodeIntegration: true,
                enableRemoteModule: true,
                nodeIntegrationInWorker: true,
                allowMediaDevices: true,
                preload: path.join(__dirname, 'preload.js')
            },
            show: false,
            frame: false,
            backgroundColor: '#00000000',
            transparent: true,
        };
        const finalConfig = { ...basicConfig, ...config };
        super(finalConfig);
        if (env === 'development') {
            // 开发
            this.loadURL('http://localhost:3000');
        } else {
            // 测试 | 生产
            this.loadFile(path.resolve(__dirname, './dist/index.html'));
        }
        this.once('ready-to-show', () => {
            this.show();
        });
    }
}
function quit() {
    app.quit()
}

function createTray() {
    const iconPath = `${__dirname}/src/assets/${updateJs.getIcon(envStr)}.png`;
    const trayIcon = nativeImage.createFromPath(iconPath);
    const tray = new Tray(trayIcon);
    const contextMenu = Menu.buildFromTemplate([
        {
            label: '打开', click: () => {
                mainWindow.webContents.send('isOpenWindows');
            },
            // icon: iconPath,
        },
        {
            label: '最小化到系统托盘', click: () => {
                mainWindow.hide();
            },
            // icon: iconPath,
        },
        {
            label: '退出', click: async () => {
                quit()
            },
            // icon: iconPath,
        },
    ]);
    tray.setToolTip(updateJs.getTitle(envStr));
    tray.setContextMenu(contextMenu);
    tray.on('click', () => {
        mainWindow.webContents.send('isOpenWindows');
    });
}

function createWindow() {
    mainWindow = new AppWindow();
    mainWindow.focus();
}
const additionalData = { myKey: 'myValue' }
app.on('ready', () => {
    const gotTheLock = app.requestSingleInstanceLock(additionalData)
    if (gotTheLock) {
        app.getPath('crashDumps')
        crashReporter.start({
            uploadToServer: false,
            ignoreSystemCrashHandler: false
        })
        env = process.argv.find((arg) => arg.startsWith('--env='))?.split('=')[1];
        if (env === 'development') {
            Object.defineProperty(app, 'isPackaged', {
                get() {
                    return true
                }
            })
            autoUpdater.updateConfigPath = path.join('latest.yml')
        }
        createWindow()
        regKey = new Registry({
            hive: Registry.HKCU,
            key: '\\Software\\ZhiHuiXiang'
        });
        // 获取当前脚本所在目录的绝对路径
        const currentDirectory = __dirname;
        // 获取安装父目录
        const parentDirectory = path.resolve(currentDirectory, '..');
        const customFolderPath = path.join(parentDirectory, 'Downloads');
        if (!fs.existsSync(customFolderPath)) {
            // 如果不存在，则创建文件夹
            fs.mkdirSync(customFolderPath);
        }
        // 监听f12打开控制台
        mainWindow.webContents.on('before-input-event', (event, input) => {
            if (input.key === 'F12') {
                mainWindow.webContents.openDevTools()
            }
        });
        // 监听移动
        mainWindow.on('move', () => {
            // 如果是全屏自动恢复到上次窗口大小
            if (isMaximized) {
                mainWindow.unmaximize()
                isMaximized = false;
            }
            if (mainWindow.isMaximized()) {
                isMaximized = true;
            }
        });
        ipcMain.handle('setEnv', (event, str) => {
            envStr = str;
            if (startNumber === 0) {
                updateHandle() // 检查更新
                setInterval(() => {
                    updateHandle() // 每一小时检查更新
                }, 1000 * 60 * 60)
                createTray()
                startNumber++
            }
        });
        // socket
        ipcMain.handle('startSignalr', (event, user) => {
            startSignalr(user)
        });
        ipcMain.handle('offSignalr', (event) => {
            if (connection) {
                connection.off('ReceiveMessage');
                connection.off('Operation');
                connection.off('ForceExitRoom');
                connection.off('AllLeave');
                connection.off('ShowUser');
                connection.off('RefreshView');
                connection.off('UserJoined');
                connection.off('UserLeave');
                connection.off('OperAllMicr');
                connection.off('OperMicr');
                connection.off('OperCamera');
                connection.off('ManagerRefresh');
                connection.off('ApplyToSpeak');
                connection.off('Watch');
                connection.off('DriverList');
                connection.off('SetDriver');
                connection.off('ShowDriverList');
                connection.off('ModifyNickName');
            }
        });
        ipcMain.handle('onStop', (event) => {
            if (connection) {
                mainWindow.webContents.send('changeLocalStorage', {
                    isSignalr: false,
                });
                connection.off('Invitation');
                connection.off('ForceLogout');
                connection.stop()
                connection = ""
            }
        });
        ipcMain.handle('onInvoke', async (event, str, data) => {
            switch (str) {
                case 'sendChannelMsg':
                    await connection.invoke(str, data.roomNum, data.msg)
                    break;
                case 'sendOper':
                    // 4:屏幕共享
                    await connection.invoke(str, data.roomNum, data.type)
                    break;
                case 'getDrivers':
                    // 获取某个人的设备列表
                    await connection.invoke(str, data.uid)
                    break;
                case 'sendDrivers':
                    // 发送设备列表给某个人
                    await connection.invoke(str, data.uid, data.driversJsonString)
                    break;
                case 'setDrivers':
                    // 设置某个人的设备列表
                    await connection.invoke(str, data.uid, data.driversJsonString)
                    break;
                case 'joinChannel':
                    // 设置某个人的设备列表
                    await connection.invoke(str, data.roomNum, data.enableMicr, data.enableCamera, data.isRoomManager || false)
                    break;
                case 'levelChannel':
                    // 设置某个人的设备列表
                    await connection.invoke(str, data.roomNum)
                    break;
            }
        });
        ipcMain.handle('onOtherSignalr', (event) => {
            if (connection) {
                // 邀请
                connection.on("Invitation", (roomNum, roomName, InviterName) => {
                    mainWindow.webContents.send('onOtherSignalr', {
                        key: 'Invitation',
                        roomNum, roomName, InviterName
                    });
                });
                // 退出
                connection.on("ForceLogout", (msg) => {
                    mainWindow.webContents.send('onOtherSignalr', {
                        key: 'ForceLogout',
                        msg
                    });
                });
            }
        });
        ipcMain.handle('onSignalr', (event) => {
            if (connection) {
                // 聊天
                connection.on("ReceiveMessage", (uid, userName, message, timestamp) => {
                    mainWindow.webContents.send('onSignalr', {
                        key: 'ReceiveMessage',
                        uid, message, userName, timestamp
                    })
                });
                // 扩展操作
                connection.on("Operation", (type) => {
                    mainWindow.webContents.send('onSignalr', {
                        key: 'Operation',
                        type
                    })
                });
                // 移出会议
                connection.on("ForceExitRoom", () => {
                    mainWindow.webContents.send('onSignalr', {
                        key: 'ForceExitRoom',
                    })
                });
                // 全员离开房间
                connection.on("AllLeave", () => {
                    mainWindow.webContents.send('onSignalr', {
                        key: 'AllLeave',
                    })
                });
                // 全员看他
                connection.on("ShowUser", (uid, uname, operUid, operUserName) => {
                    mainWindow.webContents.send('onSignalr', {
                        key: 'ShowUser',
                        uid,
                        uname,
                        operUid,
                        operUserName,
                    })
                });
                // 更新视图模式
                connection.on("RefreshView", (type) => {
                    mainWindow.webContents.send('onSignalr', {
                        key: 'RefreshView',
                        type
                    })
                });
                // 用户加入频道回调
                connection.on("UserJoined", (user) => {
                    mainWindow.webContents.send('onSignalr', {
                        key: 'UserJoined',
                        user,
                    })
                });
                // 用户退出频道回调
                connection.on("UserLeave", (uid) => {
                    mainWindow.webContents.send('onSignalr', {
                        key: 'UserLeave',
                        uid,
                    })
                });
                // 所有用户开闭麦
                connection.on("OperAllMicr", (enableMicr, uid) => {
                    mainWindow.webContents.send('onSignalr', {
                        key: 'OperAllMicr',
                        enableMicr,
                        uid
                    })
                });
                // 用户关闭开启麦克风
                connection.on("OperMicr", (user, operUid) => {
                    mainWindow.webContents.send('onSignalr', {
                        key: 'OperMicr',
                        user,
                        operUid
                    })
                });
                // 用户开启关闭摄像头
                connection.on("OperCamera", (user, operUid) => {
                    mainWindow.webContents.send('onSignalr', {
                        key: 'OperCamera',
                        user,
                        operUid
                    })
                });
                // 发言人用户信息刷新
                connection.on("ManagerRefresh", (user, uid) => {
                    mainWindow.webContents.send('onSignalr', {
                        key: 'ManagerRefresh',
                        user,
                        uid
                    })
                });
                // 申请发言
                connection.on("ApplyToSpeak", (uid, uname) => {
                    mainWindow.webContents.send('onSignalr', {
                        key: 'ApplyToSpeak',
                        uid,
                        uname
                    })
                });
                // 管理员查看随机用户
                connection.on("Watch", (watchUids) => {
                    mainWindow.webContents.send('onSignalr', {
                        key: 'Watch',
                        watchUids
                    })
                });
                // 设备列表
                connection.on("DriverList", (callerUid) => {
                    mainWindow.webContents.send('onSignalr', {
                        key: 'DriverList',
                        callerUid
                    })
                });
                // 设置设备
                connection.on("SaveDriver", (driver) => {
                    mainWindow.webContents.send('onSignalr', {
                        key: 'SaveDriver',
                        driver
                    })
                });
                // 显示设备列表
                connection.on("ShowDriverList", (driversJsonString) => {
                    mainWindow.webContents.send('onSignalr', {
                        key: 'ShowDriverList',
                        driversJsonString
                    })
                });
                // 修改用户名称
                connection.on("ModifyNickName", (uid, nickName) => {
                    mainWindow.webContents.send('onSignalr', {
                        key: 'ModifyNickName',
                        uid,
                        nickName
                    })
                });
            }
        });
        // 放大缩小退出窗口
        ipcMain.handle('setViewStatus', async (event, status) => {
            switch (status) {
                case 'quit':
                    await mainWindow.webContents.send('onQuit');
                    break;
                case 'maximize':
                    mainWindow.maximize()
                    break;
                case 'unmaximize':
                    mainWindow.unmaximize()
                    break;
                case 'minimize':
                    mainWindow.minimize()
                    break;
                case 'hide':
                    mainWindow.hide()
                    break;
                case 'show':
                    mainWindow.show()
                    mainWindow.focus();
                    mainWindow.setSkipTaskbar(false)
                    mainWindow.setResizable(true)
                    mainWindow.setAlwaysOnTop(false)
                    break;
            }
        });
        // 导出是否全屏
        ipcMain.handle('getIsMaximized', () => {
            return mainWindow.isMaximized();
        });
        // 获取app路径
        ipcMain.handle('getAppPath', () => {
            return app.getAppPath();
        });
        // 获取版本号
        ipcMain.handle('getVersion', () => {
            return app.getVersion();
        });
        // 获取窗口是否显示
        ipcMain.handle('isVisible', () => {
            return mainWindow.isVisible();
        });
        // 获取共享屏幕列表
        ipcMain.handle('getSources', async () => {
            return await desktopCapturer.getSources({
                types: ['screen']
            });
        });
        // 复制文字
        ipcMain.handle('setWriteText', (event, text) => {
            clipboard.writeText(text)
        });
        // 退出
        ipcMain.handle('quit', async (event, bool) => {
            if (bool) {
                quit()
            } else {
                await mainWindow.webContents.send('quitAndInstall');
            }
        });
        // 加入房间通知
        ipcMain.handle('joinNotification', (event, user) => {
            mainWindow.show()
            mainWindow.focus();
        });
        // 通知下载包
        ipcMain.handle('updateDownload', (event, data) => {
            if (data === '0') { // 取消下载
                cancleDownloadUpdate()
            } else if (data === '1') { // 开始下载
                downloadUpdate()
            } else if (data === '2') { // 下载完成 点击安装
                quitAndInstall()
            }
        });
        // 选择文件夹
        ipcMain.handle('selectFilePath', async (event, data) => {
            const result = await dialog.showOpenDialog({
                properties: ['openDirectory']
            });
            if (result.canceled) {

            } else {
                switch (data.key) {
                    case 'shareFilesPath':
                    case 'recordingFilesPath':
                        mainWindow.webContents.send('onFilePath', result.filePaths[0] + '\\', data.key);
                        break;
                    default:
                        mainWindow.webContents.send('downFile', {
                            downFilePaths: result.filePaths[0] + '\\',
                            fileName: data.fileName,
                            filePath: data.filePath,
                        });
                        break;
                }
            }
        });
        // 获取桌面大小
        ipcMain.handle('getWindowSize', (event, config) => {
            const primaryDisplay = screen.getPrimaryDisplay()
            const { width, height } = primaryDisplay.workAreaSize
            return { width, height }
        });
        // 设置桌面应用基础属性
        ipcMain.handle('setMainWindowSize', (event, config) => {
            if (config.width === 250) {
                mainWindow.setSkipTaskbar(true)
                mainWindow.setResizable(false)
                mainWindow.setAlwaysOnTop(true, 'screen-saver')
            }
            // 设置最小窗口尺寸
            mainWindow.setMinimumSize(config.width, config.height);
            // 设置最大尺寸
            const primaryDisplay = screen.getPrimaryDisplay()
            const { width, height } = primaryDisplay.workAreaSize
            if (config.key === 'login') {
                mainWindow.setMaximumSize(config.width, config.height);
            } else {
                mainWindow.setMaximumSize(width, height);
            }
            // 设置窗口尺寸
            mainWindow.setSize(config.width, config.height)
            // 设置窗口位置使其居中于当前屏幕
            mainWindowCenter()
        });
        // 写入注册表
        ipcMain.handle('setRegistry', (event, uuid) => {
            regKey.create((err) => {
                if (err) {
                    return;
                }
                // 设置键和值
                regKey.set('uuid', Registry.REG_SZ, uuid, (err) => {
                    if (err) {
                        return;
                    }
                });
            });
        });
        // 读取注册表
        ipcMain.handle('getRegistry', async () => {
            return new Promise((resolve, reject) => {
                regKey.get('uuid', (err, item) => {
                    resolve(item)
                })
            });
        });
        // 创建子窗口
        ipcMain.handle('createChildWindow', (event, config) => {
            const child = new BrowserWindow({
                parent: mainWindow,
                webPreferences: {
                    contextIsolation: false,
                    nodeIntegration: true,
                    enableRemoteModule: true,
                    nodeIntegrationInWorker: true,
                    allowMediaDevices: true,
                    preload: path.join(__dirname, 'preload.js')
                },
                show: false,
                frame: false,
                backgroundColor: '#00000000',
                transparent: true,
                width: config.width,
                height: config.height,
            })
            if (envStr === 'development') {
                // 开发
                child.loadURL(config.url)
            } else {
                // 测试 | 生产
                child.loadURL(`file://${path.join(__dirname, './dist/index.html')}#/${config.key}`);
            }
            childWindow[config.key] = child
            child.once('ready-to-show', () => {
                if (config.show) {
                    childWindow[config.key].show()
                }
                childWindow[config.key].setAlwaysOnTop(true, 'screen-saver')
                childWindow[config.key].setSkipTaskbar(true)
                windowOperation(config)
            })
            child.webContents.on('before-input-event', (event, input) => {
                if (input.key === 'F12') {
                    child.webContents.openDevTools()
                }
            });
        });
        // 关闭子窗口
        ipcMain.handle('closeChildWindow', (event, key) => {
            if (key === 'shareScreenWindow') {
                for (const k in childWindow) {
                    if (childWindow[k]) {
                        childWindow[k].close()
                        childWindow[k] = ""
                    }
                }
            } else {
                childWindow[key].close()
                childWindow[key] = ""
            }
        });
        // 设置子窗口
        ipcMain.handle('setChildWindow', (event, config) => {
            switch (config.key) {
                case 'shareScreenWindow':
                    childWindow[config.key].setBounds({ width: config.width })
                    break;
                case 'chatSmallWindow':
                    childWindow[config.key].setBounds({ height: config.height })
                    break;
                case 'noticeWindow':
                    childWindow[config.key].setBounds({ width: config.width, height: config.height })
                    break;
                default:
                    mainWindow.setMinimumSize(250, config.height);
                    mainWindow.setMaximumSize(250, config.height);
                    mainWindow.setSize(250, config.height)
                    break;
            }
        });
        // 隐藏显示子窗口
        ipcMain.handle('setChildWindowShow', (event, config) => {
            if (config.key === 'noticeWindow') {
                if (config.bool) {
                    childWindow[config.key].show()
                } else {
                    if (childWindow[config.key].isVisible()) {
                        childWindow[config.key].hide()
                    }
                }
            } else {
                if (config.bool) {
                    childWindow[config.key].hide()
                } else {
                    if (childWindow[config.key].isVisible()) {
                        childWindow[config.key].hide()
                    } else {
                        childWindow[config.key].show()
                    }
                }
            }
        });
        // 定位主窗口
        ipcMain.handle('setPosition', (event, data) => {
            const display = screen.getDisplayMatching({ ...mainWindow.getBounds() });
            const { width, height } = display.size
            switch (data) {
                case 'right':
                    x = width - mainWindow.getSize()[0];
                    mainWindow.setPosition(x - 40, 40);
                    break;
                default:
                    break;
            }
        });
        // 窗口通信
        ipcMain.handle('windowHandleMessage', (event, data) => {
            if (childWindow[data.key]) {
                childWindow[data.key].webContents.send('windowHandleMessageCallBack', data)
            }
        });
    }
});
// 检测更新，在你想要检查更新的时候执行，renderer事件触发后的操作自行编写
function updateHandle() {
    autoUpdater.checkForUpdates()
    // autoUpdater.checkForUpdatesAndNotify().catch();
    const message = {
        error: '检查更新出错',
        checking: '正在检查更新……',
        updateAva: '检测到新版本，正在下载……',
        updateNotAva: '已经是最新版本，不用更新'
    }
    autoUpdater.setFeedURL(updateJs.getUpdateUrl(envStr))
    autoUpdater.autoDownload = false // 不自动下载安装包
    autoUpdater.autoInstallOnAppQuit = false // 不自动安装
    autoUpdater.on('error', function (error) {
        sendUpdateMessage(message.error)
    })
    autoUpdater.on('checking-for-update', function () {
        sendUpdateMessage(message.checking)
    })
    autoUpdater.on('update-available', function (info) {
        let messageStr = JSON.stringify({ type: '0' })
        setTimeout(() => {
            sendUpdateMessage(messageStr)
        }, 5000)
    })
    autoUpdater.on('update-not-available', function (info) {

    })
    // 更新下载进度事件
    autoUpdater.on('download-progress', function (progressObj) {
        let message = JSON.stringify({
            type: '1',
            value: progressObj.percent
        })
        sendUpdateMessage(message)
    })
    autoUpdater.on('update-downloaded', function (event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate) {
        let message = JSON.stringify({
            type: '2',
        })
        sendUpdateMessage(message)
    })
}

// 通过main进程发送事件给renderer进程，提示更新信息
// type: 0 检测到需要更新（打开窗口） 1 正在下载更新包
function sendUpdateMessage(text) {
    mainWindow.webContents.send('update', text)
}

// 下载最新的包
function downloadUpdate() {
    autoUpdater.downloadUpdate(cancellationToken)
}

// 取消下载
function cancleDownloadUpdate() {
    autoUpdater.downloadUpdate(cancellationToken)
    // stop download
    cancellationToken.cancel()
}

// 完成下载立即安装
function quitAndInstall() {
    autoUpdater.quitAndInstall();
}

function windowOperation(config) {
    const child = childWindow[config.key];
    const display = screen.getDisplayMatching({ ...child.getBounds() });
    const { width, height } = display.size
    let x, y;
    child.setResizable(false)
    switch (config.key) {
        case 'shareScreenWindow':
            x = Math.round((display.workArea.width - child.getSize()[0]) / 2);
            child.setPosition(x, 0);
            break;
        case 'chatSmallWindow':
            y = height - child.getSize()[1];
            child.setPosition(40, y - 200);
            break;
        case 'noticeWindow':
            x = width - child.getSize()[0];
            y = height - child.getSize()[1];
            child.setPosition(x, y - 80);
            break;
    }
}
// 主窗口居中
function mainWindowCenter() {
    const display = screen.getDisplayMatching({ ...mainWindow.getBounds() });
    const x = Math.round((display.workArea.width - mainWindow.getSize()[0]) / 2);
    const y = Math.round((display.workArea.height - mainWindow.getSize()[1]) / 2);
    mainWindow.setPosition(x, y);
}

const startSignalr = async (user) => {
    connection = new signalR.HubConnectionBuilder()
        .withUrl(`${envStr === 'development' ? 'http://192.168.2.9:5192' : 'https://meeting-api.23544.com/pc'}/session-manage`, {
            skipNegotiation: true,
            transport: signalR.HttpTransportType.WebSockets,
            accessTokenFactory: () => user.token
        })
        .withAutomaticReconnect([0, 3000, 3000, 3000])
        .build();
    mainWindow.webContents.send('changeLocalStorage', {
        isSignalr: true,
        reconnect: true,
    });
    connection.onreconnected(async () => {
        mainWindow.webContents.send('changeLocalStorage', {
            reconnect: true,
        });
    });
    connection.onreconnecting(async () => {
        onStart()
        mainWindow.webContents.send('changeLocalStorage', {
            reconnect: false,
        });
    });
    connection.start();
}

const onStart = async () => {
    if (connection) {
        if (connection.state === signalR.HubConnectionState.Disconnected) {
            connection.start().then(() => {
                mainWindow.webContents.send('changeLocalStorage', {
                    reconnect: true,
                });
            }).catch((err) => {

            });
        }
        if (connection.state !== signalR.HubConnectionState.Connected) {
            setTimeout(onStart, 3000);
        }
    }
}