
const { execSync } = require("child_process");
const MSG_CODEGEN_LOG = 'CODEGEN ANGULAR APP: ';
const MSG_NG_RUNTIME_LOG = 'APP NG RUNTIME NODE MODULES: ';
const MSG_APP_RUNTIME_WM_BUILD_LOG = 'APP RUNTIME WM BUILD : ';

const MSG_ANGULAR_CODEGEN_SUCCESS = 'ANGULAR_CODEGEN_SUCCESS';
const MSG_APP_RUNTIME_WM_BUILD_SUCCESS = 'WAVEMAKER_APP_RUNTIME_WM_BUILD_SUCCESS';
const MSG_NG_RUNTIME_SUCCESS = 'APP_NG_RUNTIME_SUCCESS';
/**
 * Read the console arguments and prepare the key value pairs.
 * @returns Object console arguments as key value pairs
 */
const getArgs = () => {
    const args = {};
    process.argv
        .slice(2, process.argv.length)
        .forEach(arg => {
            if (arg.slice(0, 2) === '--') {
                const longArg = arg.split('=');
                const longArgFlag = longArg[0].slice(2, longArg[0].length);
                const longArgValue = longArg.length > 2 ? longArg.slice(1, longArg.length).join('=') : longArg[1];
                args[longArgFlag] = longArgValue;
            }
        });
    return args;
}

const args = getArgs();

/**
 * Generate the npm package version to publish into the npm package.
 * @param {*} publishVersion  
 * @returns string foramt npm version
 */
 const generateNpmVersion = (publishVersion, isProd) => {
    publishVersion = publishVersion || '';
    const splits = publishVersion.split('.');
    while (splits.length < 4) {
        splits.push('0');
    }
    let npmVer = '';
    splits.forEach((v, i) => {
        if (i === 3) {
            npmVer += `-${(isProd?'rc':'next')}.`;
        } else if (i > 0) {
            npmVer += '.';
        }
        npmVer += v;
    });
    return npmVer;
};


/**
 * To run the system command via node  child process.
 * @param {*} cmd Command in string format to execute in node environment
 * @param {*} errorCallback callback if anything needs to be handled on command failure 
 */
const executeSyncCmd = (cmd, errorCallback, msg) => {
    try {
        console.log(msg + 'Current running cmd: ' + cmd)
        execSync(cmd, { stdio: 'inherit' });
    } catch (err) {
        if (errorCallback) {
            errorCallback(err);
        }
        console.log(msg + 'FAILED command: ' + cmd, err);
        process.exit(err.code || err.pid);
    }
}

/**
 *  Build the string with console argument
 * @returns string format console arguments
 */
const buildArgs = () => {
    let cmdArgs = ' --nodeVMArgs="' + args.nodeVMArgs + '" --ngBuildParams="' + args.ngBuildParams + '" --runtimeUIVersion="' + args.runtimeUIVersion + '"  --appSrc="' + args.appSrc + '" --appTarget="' + args.appTarget + '" --codegenPath="' + args.codegenPath + '"';;
    return cmdArgs;
}

// TO capture the ctrl+C signal
process.on('SIGINT', function (e) {
    console.log("Caught interrupt signal", e);
    process.exit(1);
});


/**
 * This function is executed successfully if the system node version is in a specified range. If not, the process will be killed
 * 
 */
const checkNodeVersion = () => {
    if (!isSystemHasValidNodeVersion()) {
        console.log("\x1b[31m", "-------******* Project configuration doesn't meet, Please install and use Node Version between >=10.15.0  <10.16.0 *******-------");
        console.log("\x1b[31m", "-------******* Your current Node Version is: " + process.versions.node + " *******-------");
        process.exit(1);
    } else {
        console.log("\x1b[47m\x1b[32m%s\x1b[0m", "-------******* Good to Go with your Node Version: " + process.versions.node + " *******-------");
    }

}

// Return 1 if systemInstalledVersion > requiredVersion
// Return -1 if systemInstalledVersion < requiredVersion
// Return 0 if systemInstalledVersion == requiredVersion
const compareNodeVersion = (requiredVersion) => {
    let systemInstalledVersion = process.versions.node;
    if (systemInstalledVersion === requiredVersion) {
        return 0;
    }

    let systemInstalledVersion_components = systemInstalledVersion.split(".");
    let requiredVersion_components = requiredVersion.split(".");

    let len = Math.min(systemInstalledVersion_components.length, requiredVersion_components.length);

    // loop while the components are equal
    for (let i = 0; i < len; i++) {
        // systemInstalledVersion bigger than requiredVersion
        if (parseInt(systemInstalledVersion_components[i]) > parseInt(requiredVersion_components[i])) {
            return 1;
        }

        // requiredVersion bigger than systemInstalledVersion
        if (parseInt(systemInstalledVersion_components[i]) < parseInt(requiredVersion_components[i])) {
            return -1;
        }
    }

    // If one's a prefix of the other, the longer one is greater.
    if (systemInstalledVersion_components.length > requiredVersion_components.length) {
        return 1;
    }

    if (systemInstalledVersion_components.length < requiredVersion_components.length) {
        return -1;
    }

    // Otherwise they are the same.
    return 0;
}

/**
 *  To restrict the node version in the given range
 * @returns boolean true/false
 */
const isSystemHasValidNodeVersion = () => {
    const nodeMinVersion = '10.15.0';
    const nodeMaxVersion = '10.15.9999';
    if (compareNodeVersion(nodeMinVersion) >= 0 && compareNodeVersion(nodeMaxVersion) < 0) {
        return true;
    } else {
        return false;
    }
}



module.exports = {
    executeSyncCmd,
    args,
    buildArgs,
    checkNodeVersion,
    generateNpmVersion,
    MSG_CODEGEN_LOG,
    MSG_NG_RUNTIME_LOG,
    MSG_NG_RUNTIME_SUCCESS,
    MSG_APP_RUNTIME_WM_BUILD_LOG,
    MSG_APP_RUNTIME_WM_BUILD_SUCCESS,
    MSG_ANGULAR_CODEGEN_SUCCESS
    
}
