import fs from "fs";
import { ChildProcess } from "child_process";
import colors from "./console-colors";
import kill from "kill-port";
import preflightFn from "./preflight";
import run from "./run";
import killChild from "./kill-child";

let redeployments = 0;

let childProcess: ChildProcess | null = null;

const pTitle = "nodecid";
process.title = pTitle;

/**
 * # Start the process
 * @param {object} param0
 * @param {string} param0.command
 * @param {string[] | string} param0.preflight
 * @param {string[] | string} [param0.postflight]
 * @param {string} param0.redeploy_file
 * @param {string | number | (string | number)[]} [param0.port] - The port to kill on rebuild
 * @param {boolean} [param0.first_run] - Whether to run the preflight on first run. Default `false`
 */
export default function startProcess({
    command,
    preflight,
    postflight,
    redeploy_file,
    port,
    first_run,
}: {
    command: string;
    preflight: string[] | string;
    postflight?: string[] | string;
    redeploy_file: string;
    port?: string | number | (string | number)[];
    first_run?: boolean;
}) {
    try {
        if (first_run) {
            console.log("First Run ...");
            const runPreflight = preflightFn(preflight);
        }

        if (!preflight) {
            console.log(
                `${colors.FgRed}Error:${colors.Reset} No preflight included in config file. If you don't want to run any preflight command simply add an empty array.`
            );
            process.exit();
        }

        childProcess = run(command);

        if (!childProcess) {
            console.log(
                `${colors.FgRed}Error:${colors.Reset} Process couldn't start. Exiting...`
            );
            process.exit();
        }

        console.log("Watching", redeploy_file);

        fs.watchFile(redeploy_file, { interval: 100 }, (curr, prev) => {
            console.log(`${colors.BgBlue}File Changed${colors.Reset}`);

            if (redeployments == 0) return;

            if (childProcess) {
                console.log("******************************");
                console.log(
                    `******** ${colors.FgBlue}Rebuilding ${colors.FgMagenta}${redeployments}${colors.Reset} ********`
                );
                console.log("******************************");

                try {
                    const runPreflight = preflightFn(preflight);

                    if (!runPreflight) {
                        // TODO: Action to take if preflight fails

                        console.log(
                            `${colors.FgRed}Error:${colors.Reset} Preflight Failed.`
                        );
                    } else {
                        killChild(port).then((kill) => {
                            if (kill) {
                                childProcess = run(command);

                                if (postflight) {
                                    const runPostflight = preflightFn(
                                        postflight,
                                        true
                                    );

                                    if (!runPostflight) {
                                        // TODO: Action to take if postflight fails

                                        console.log(
                                            `${colors.FgRed}Error:${colors.Reset} Postflight Failed.`
                                        );
                                    }
                                }
                            } else {
                                process.exit();
                            }
                        });
                    }
                } catch (error: any) {
                    console.log(
                        `${colors.FgRed}Error:${colors.Reset} killing child processes => ${error.message}`
                    );
                    process.exit();
                }
            }
        });
    } catch (error: any) {
        console.log(
            `${colors.FgRed}Error:${colors.Reset} First run failed! => ${error.message}`
        );
    }
}
