console.log("Initializing...")
const { app, BrowserWindow, ipcMain, Menu, dialog } = require('electron')
const fs = require('fs');
const prompt = require('electron-prompt');
const path = require('path');
const pino = require('pino')
const pretty = require('pino-pretty');
const https = require('node:https');
const LocalStorage = require('node-localstorage').LocalStorage
const ipc = ipcMain

const logger = pino(pretty())
const localStorage = new LocalStorage('.');

process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true';

var currentprojectpath = null;
var currentprojectname = null;
var currentprojectopen = false;
var appexiting = false;
var appreloading = false;
var currentworkspacechange = false;
var isopennewproject = false;

var appstarted = false;
var version;
var gitver;

try {
    // Read package.json synchronously
    const data = fs.readFileSync('package.json', 'utf8');

    // Parse JSON
    const packageJson = JSON.parse(data);

    // Get project version
    version = packageJson.version;
} catch (err) {
    console.error("Error reading package.json:", err);
}

function checkupdate() {
    return new Promise((resolve, reject) => {
        const req = https.request({
                hostname: 'api.github.com',
                port: 443,
                path: '/repos/DPSoftware-Foundation/ccIDE/releases/latest',
                method: 'GET',
                headers: {
                'User-Agent': 'ccIDE-Check-Update-Service', // GitHub API requires a User-Agent header
            }
        }, (res) => {
            let data = '';
            res.setEncoding('utf8');
            res.on('data', (chunk) => {
                data += chunk;
            });
            res.on('end', () => {
                try {
                    const json = JSON.parse(data);
                    resolve(json.tag_name); // Return the tag_name or other relevant data
                } catch (e) {
                    reject('Error parsing JSON: ' + e.message);
                }
            });
        });
    
        req.on('error', (e) => {
            reject('Error fetching release: ' + e.message);
        });
    
        req.end();
    });
}

function normalizeVersion(version, length = 4) {
    // Split the version string into parts and pad with zeros if necessary
    return version.split('.').map(part => part.padStart(2, '0')).concat(Array(length).fill('00')).slice(0, length).join('.');
}

app.whenReady().then(async () => {
    logger.info("Initializing splash window...")
    reloadall(false);
    var splash = new BrowserWindow({
        width: 720, 
        height: 400, 
        icon: path.join(__dirname, 'assets', 'ccIDEIcon.ico'),
        transparent: true, 
        frame: false, 
        center: true,
        webPreferences: {
            nodeIntegration: true,
            contextIsolation: false,
        },
        resizable: false
    });

    splash.loadFile('src/splash.html');

    while (!splash.isVisible()) {}

    // checkupdate
    logger.info("Checking for new update...")
    splash.webContents.send("change-status", "Checking for new update...")
    
    try {
        const latestRelease = await checkupdate();
        // Store the version or use it as needed
        gitver = latestRelease;
    } catch (error) {
        logger.error('Error in update check:', error);
    }

    logger.info("Version in github: " + gitver)
    logger.info("Current version: " + version)

    const normalizedAppVersion = normalizeVersion(version);
    const normalizedReleaseVersion = normalizeVersion(gitver);

    if (normalizedAppVersion >= normalizedReleaseVersion) {
        logger.info("Software is up-to-date.");
    } else {
        logger.info("A new update is available: " + gitver)
        var is_not_skip_update = localStorage.getItem('skip_update_version') != normalizedAppVersion;
        var is_ignore = localStorage.getItem('ignore_update');
        if (is_ignore || is_not_skip_update) {
            const result = dialog.showMessageBoxSync({
                type: 'question',
                buttons: ['Update', 'Ignore', 'Skip'],
                defaultId: 0,
                title: 'Update Available',
                message: `A new version (${gitver}) is available. Do you want to update now?`,
                detail: 'Click "Update" to go to the release page, "Ignore" to ignore this update, or "Skip" to skip this version.'
            });
            switch (result.response) {
                case 0: // 'Update'
                    (async () => {
                        try {
                            const { default: open } = await import('open');
                        
                            await open('https://github.com/DPSoftware-Foundation/ccIDE/releases/latest');
                            console.log('URL opened in default browser');
                        } catch (err) {
                            console.error('Error opening URL:', err);
                        }
                    })();
                    break;
                case 1: // 'Ignore'
                    localStorage.setItem('ignore_update', true);
                    break;
                case 2: // 'Skip'
                    localStorage.setItem('skip_update_version', normalizedReleaseVersion);
                    break;
            }
        }
    }

    logger.info("Initializing main windows...")
    splash.webContents.send("change-status", "Initializing main windows...")

    const win = new BrowserWindow({
        width: 1280,
        height: 720,
        icon: path.join(__dirname, 'assets', 'ccIDEIcon.ico'),
        webPreferences: {
            devTools: true,
            nodeIntegration: true,
            enableRemoteModule: true,
            contextIsolation: false,
        },
        show: false,
        center: true,
    })
    
    try {
        win.loadFile('src/index.html');
    } catch {
        try {
            win.loadFile('dist_src/index.html');
        } catch {
            dialog.showErrorBox("Error on startup", "Can't find index.html");
        }
    }
    win.setTitle(`ccIDE v${version}`)

    ipc.once('ready', () => {
        splash.webContents.send("isloaded")
        splash.webContents.send("change-status", "Thanks for using software from DPSoftware.")
        splash.webContents.send("change-title", `ccIDE v${version}`)
        logger.info("Ready!")
        if (splash) {
            splash.hide();
        }
        win.show();
        //win.maximize();
        appstarted = true;
    });

    ipc.on("splash-close", (event) => {
        if (appstarted) {
            splash.hide();
        } else {
            splash.close();
            win.close();
        }
    })

    ipc.on('erroronstart', (event, errormessage) => {
        logger.error(errormessage)
        dialog.showErrorBox("Error on startup", errormessage);
        //win.openDevTools();
    });

    ipc.on('error', (event, errormessage) => {
        logger.error(errormessage)
        dialog.showErrorBox("Error", errormessage);
        //win.openDevTools();
    });

    ipc.on('update-log-status', (event, status) => {
        logger.info(status)
        if (!appstarted) {
            splash.webContents.send("change-status", status)
        } 
    });
    
    //app.on('activate', () => {
    //    if (BrowserWindow.getAllWindows().length === 0) {
    //        createWindow()
    //    }
    //})

    function reloadall(isloaded=true) {
        currentprojectpath = null;
        currentprojectname = null;
        currentprojectopen = false;
        currentworkspacechange = false;
        appexiting = false;
        appreloading = false;
        isopennewproject = false;
        if (isloaded) {
            win.setTitle(`ccIDE v${version}`)
            win.reload();
        }
    }

    logger.info("Settings up menu bar...")
    // Define a custom menu template
    const menuTemplate = [
        {
            label: 'File',
            submenu: [
                {
                    label: 'New',
                    accelerator: 'CmdOrCtrl+N',
                    click: () => {
                        if (currentworkspacechange) {
                            const result = dialog.showMessageBoxSync({
                                type: 'question',
                                buttons: ['Save', 'Don\'t Save', 'Cancel'],
                                defaultId: 2,
                                title: 'Save Changes',
                                message: "Your project is not saved",
                            });
                            if (result === 1) {
                                // Don't save
                                reloadall();
                            } else if (result === 0) {
                                // Save 
                                appreloading = true;
                                win.webContents.send('save-workspace-request');
                            }
                        } else {
                            reloadall();
                        }
                    }
                },
                {
                    label: 'Open',
                    accelerator: 'CmdOrCtrl+O',
                    click: () => {
                        if (currentworkspacechange) {
                            const result = dialog.showMessageBoxSync({
                                type: 'question',
                                buttons: ['Save', 'Don\'t Save', 'Cancel'],
                                defaultId: 2,
                                title: 'Save Changes',
                                message: "Your project is not saved",
                            });
                            if (result === 1) {
                                // Don't save
                                dialog.showOpenDialog(win, {
                                    title: 'Open Project',
                                    defaultPath: app.getPath('documents'),
                                    filters: [
                                        { name: 'ComputerCraft Project', extensions: ['ccp'] }
                                    ],
                                    properties: ['openFile']
                                }).then(result => {
                                    if (!result.canceled) {
                                        const filePath = result.filePaths[0];
                                        
                                        fs.readFile(filePath, 'utf8', (err, json) => {
                                            if (err) {
                                                console.error('Error loading workspace:', err);
                                                return;
                                            }
                                            win.webContents.send('load-workspace', json);
    
                                            currentprojectpath = result.filePaths[0]
                                            currentprojectname = path.basename(result.filePaths[0]);
                                            currentprojectopen = true;
    
                                            win.setTitle(`${currentprojectname} | ccIDE v${version}`)
                                        });
    
                                    }
                                }).catch(err => {
                                    console.error('Error showing open dialog:', err);
                                });
                            } else if (result === 0) {
                                // Save 
                                isopennewproject = true;
                                win.webContents.send('save-workspace-request');
                            }
                        } else {
                            dialog.showOpenDialog(win, {
                                title: 'Open Project',
                                defaultPath: app.getPath('documents'),
                                filters: [
                                    { name: 'ComputerCraft Project', extensions: ['ccp'] }
                                ],
                                properties: ['openFile']
                            }).then(result => {
                                if (!result.canceled) {
                                    const filePath = result.filePaths[0];
                                    
                                    fs.readFile(filePath, 'utf8', (err, json) => {
                                        if (err) {
                                            console.error('Error loading workspace:', err);
                                            return;
                                        }
                                        win.webContents.send('load-workspace', json);

                                        currentprojectpath = result.filePaths[0]
                                        currentprojectname = path.basename(result.filePaths[0]);
                                        currentprojectopen = true;

                                        win.setTitle(`${currentprojectname} | ccIDE v${version}`)
                                    });

                                }
                            }).catch(err => {
                                console.error('Error showing open dialog:', err);
                            });
                        }
                    }
                },
                {
                    label: 'Save',
                    accelerator: 'CmdOrCtrl+S',
                    click: () => {
                        win.webContents.send('save-workspace-request');
                    }
                },
                {
                    label: 'Save as',
                    accelerator: 'CmdOrCtrl+Shift+S',
                    click: () => {
                        currentprojectopen = false
                        win.webContents.send('save-workspace-request');
                    }
                },
                { type: 'separator' },
                {
                    label: 'Export',
                    submenu: [
                        {
                            label: "Export Lua",
                            accelerator: 'CmdOrCtrl+Shift+L',
                            click: () => {
                                win.webContents.send('export-lua-request');
                            }
                        }
                    ]
                },
                { type: 'separator' },
                {
                    label: 'Exit',
                    accelerator: 'CmdOrCtrl+Q',
                    click: () => {
                        app.quit();
                    }
                }
            ]
        },
        {
            label: 'Edit',
            submenu: [
                { label: "Undo", accelerator: "CmdOrCtrl+Z", selector: "undo:" },
                { label: "Redo", accelerator: "Shift+CmdOrCtrl+Z", selector: "redo:" },
                { type: "separator" },
                { label: "Cut", accelerator: "CmdOrCtrl+X", selector: "cut:" },
                { label: "Copy", accelerator: "CmdOrCtrl+C", selector: "copy:" },
                { label: "Paste", accelerator: "CmdOrCtrl+V", selector: "paste:" },
                { label: "Select All", accelerator: "CmdOrCtrl+A", selector: "selectAll:" }
            ]
        },
        {
            label: 'Help',
            submenu: [
                { label: 'DevTools', accelerator: 'F12', click: () => {win.openDevTools()}},
                { type: 'separator' },
                {
                    label: 'About',
                    click: () => {
                        win.webContents.send("open-about")
                    }
                },
                {
                    label: 'Splash Screen',
                    click: () => {
                        if (!splash.isVisible()) {
                            splash.show();
                        } else {
                            splash.hide();
                        }
                    }
                }
            ]
        }
    ];

    // Set the custom menu
    const menu = Menu.buildFromTemplate(menuTemplate);
    Menu.setApplicationMenu(menu);

    logger.info("Settings up event...")
    
    ipc.on('prompt', (event, promptText, defaultValue) => {
        try {
            prompt({
                title: "ccIDE",
                label: promptText,
                value: defaultValue,
                inputAttrs: {
                    type: 'text', 
                    required: true
                },
                type: 'input',
                alwaysOnTop: true
            })
            .then((r) => {
                if(r === null) {
                    event.returnValue = null
                } else {
                    event.returnValue = r
                }
            })
            .catch(console.error);
        } catch (error) {
            console.error('Error showing prompt dialog:', error);
            event.returnValue = null; // or handle error appropriately
        }
    });

    ipc.on('save-workspace', (event, json) => {
        if (!currentprojectopen) {
            dialog.showSaveDialog(win, {
                title: 'Save Project',
                defaultPath: path.join(app.getPath('documents'), 'untitled.ccp'),
                filters: [
                    { name: 'ComputerCraft Project', extensions: ['ccp'] }
                ]
            }).then(result => {
                if (!result.canceled) {
                    fs.writeFile(result.filePath, JSON.stringify(json), (err) => {
                        if (err) {
                            console.error('Error saving project:', err);
                            dialog.showErrorBox("Save Project Error", err.message)
                            win.webContents.send('workspace-saved', false);
                        } else {
                            currentprojectpath = result.filePath
                            currentprojectname = path.basename(result.filePath);
                            currentprojectopen = true;

                            win.webContents.send('workspace-saved', true);

                            win.setTitle(`${currentprojectname} | ccIDE v${version}`)
                            if (currentworkspacechange) {
                                currentworkspacechange = false;
                            }
                        }
                    });
                } else {
                    win.webContents.send('workspace-saved', false);
                }
            }).catch(err => {
                console.error('Error showing save dialog:', err);
                dialog.showErrorBox("Save Project Error", err.message)
                win.webContents.send('workspace-saved', false);
            });
        } else {
            fs.writeFile(currentprojectpath, JSON.stringify(json), (err) => {
                if (err) {
                    console.error('Error saving project:', err);
                    dialog.showErrorBox("Save Project Error", err.message)
                    win.webContents.send('workspace-saved', false);
                } else {
                    currentprojectopen = true;

                    win.webContents.send('workspace-saved', true);

                    win.setTitle(`${currentprojectname} | ccIDE v${version}`)

                    if (currentworkspacechange) {
                        currentworkspacechange = false;
                    }

                    if (appexiting) {
                        app.quit();
                    }
                    if (appreloading) {
                        reloadall();
                    }
                    if (isopennewproject) {
                        dialog.showOpenDialog(win, {
                            title: 'Open Project',
                            defaultPath: app.getPath('documents'),
                            filters: [
                                { name: 'ComputerCraft Project', extensions: ['ccp'] }
                            ],
                            properties: ['openFile']
                        }).then(result => {
                            if (!result.canceled) {
                                const filePath = result.filePaths[0];
                                
                                fs.readFile(filePath, 'utf8', (err, json) => {
                                    if (err) {
                                        console.error('Error loading workspace:', err);
                                        return;
                                    }
                                    win.webContents.send('load-workspace', json);

                                    currentprojectpath = result.filePaths[0]
                                    currentprojectname = path.basename(result.filePaths[0]);
                                    currentprojectopen = true;

                                    win.setTitle(`${currentprojectname} | ccIDE v${version}`)
                                });

                            }
                        }).catch(err => {
                            console.error('Error showing open dialog:', err);
                        });
                    }
                }
            });
        }
    });

    ipc.on('export-lua', (event, data) => {
        dialog.showSaveDialog(win, {
            title: 'Save Project',
            defaultPath: path.join(app.getPath('documents'), 'main.lua'),
            filters: [
                { extensions: ['lua'] }
            ]
        }).then(result => {
            if (!result.canceled) {
                fs.writeFile(result.filePath, data, (err) => {
                    if (err) {
                        console.error('Error exporting lua from project:', err);
                        dialog.showErrorBox("Export Lua Error", err.message)
                    }
                });
            }
        }).catch(err => {
            console.error('Error exporting lua from project:', err);
            dialog.showErrorBox("Export Lua Error", err.message)
        });
    });

    ipc.on('workspace-notsave', (event) => {
        win.setTitle(`${currentprojectname}* | ccIDE v${version}`)
        currentworkspacechange = true;
    })
    ipc.on('workspace-unsave', (event) => {
        currentworkspacechange = true;
    })

    // Listen for the close event of the main window
    /*
    win.on('close', (event) => {
        event.preventDefault()
        if (currentprojectopen && !currentworkspacechange) {
            const result = dialog.showMessageBoxSync({
                type: 'question',
                buttons: ['Save', 'Don\'t Save', 'Cancel'],
                defaultId: 2,
                title: 'Save Changes',
                message: "Your project is not saved",
            });
            if (result === 1) {
                // Don't save, continue closing
                win.close();
            } else if (result === 0) {
                // Save and then quit
                appexiting = true;
                win.webContents.send('save-workspace-request');
            }
        } else {
            win.destroy();
        }
    });
    */

    win.on("closed", () => {
        logger.info("Exiting...")
        if (!splash.isDestroyed()) {
            splash.close()
        }
    })
    
})

app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') {
        app.quit();
    }
    logger.info("Exited")
});