'use strict';

const { writeFile } = require('fs/promises');
const { Readable } = require('stream');
const { resolve } = require('path');
const { parseArgs } = require('util')
const { createInterface } = require('readline');
const { inspect } = require('util');
const { runClang } = require('../lib/clang-utils');
const { evaluate } = require('../lib/parse-utils');

/**
 * @returns {Promise<string>} Version string, eg. `'v19.6.0'`.
 */
async function getLatestReleaseVersion() {
    const response = await fetch('https://nodejs.org/download/release/index.json');
    const json = await response.json();
    return json[0].version;
}

/**
 * @param {NodeJS.ReadableStream} stream
 * @param {string} destination
 * @param {boolean} verbose
 * @returns {Promise<void>} The `writeFile` Promise.
 */
function removeExperimentals(stream, destination, verbose = false) {
    return new Promise((resolve, reject) => {
        const debug = (...args) => {
            if (verbose) {
                console.log(...args);
            }
        };
        const rl = createInterface(stream);

        /** @type {Array<'write' | 'ignore' | 'preprocessor'>} */
        const mode = ['write'];

        /** @type {Array<string>} */
        const preprocessor = [];

        /** @type {Array<string>} */
        const macroStack = [];

        /** @type {RegExpMatchArray | null} */
        let matches;

        let lineNumber = 0;
        let toWrite = '';

        const handlePreprocessor = (expression) => {
            const result = evaluate(expression);

            macroStack.push(expression);

            if (result === false) {
                debug(`Line ${lineNumber} Ignored '${expression}'`);
                mode.push('ignore');
                return false;
            } else {
                debug(`Line ${lineNumber} Pushed '${expression}'`);
                mode.push('write');
                return true;
            }
        };

        rl.on('line', function lineHandler(line) {
            ++lineNumber;
            if (matches = line.match(/^\s*#if(n)?def\s+([A-Za-z_][A-Za-z0-9_]*)/)) {
                const negated = Boolean(matches[1]);
                const identifier = matches[2];
                macroStack.push(identifier);

                if (mode.length && mode[mode.length - 1] === 'ignore') {
                    debug(`Line ${lineNumber} Continued-Ignored ${identifier}`);
                    mode.push('ignore');
                    return;
                }

                debug(`Line ${lineNumber} Pushed ${identifier}`);

                if (identifier === 'NAPI_EXPERIMENTAL') {
                    if (negated) {
                        mode.push('write');
                    } else {
                        mode.push('ignore');
                    }
                    return;
                } else {
                    mode.push('write');
                }
            }
            else if (matches = line.match(/^\s*#if\s+(.+)$/)) {
                const expression = matches[1];
                if (expression.endsWith('\\')) {
                    if (preprocessor.length) {
                        reject(new Error(`Unexpected preprocessor continuation on line ${lineNumber}`));
                        return;
                    }
                    preprocessor.push(expression.substring(0, expression.length - 1));

                    mode.push('preprocessor');
                    return;
                } else {
                    if (!handlePreprocessor(expression)) {
                        return;
                    }
                }
            }
            else if (line.match(/^#else(?:\s+|$)/)) {
                const identifier = macroStack[macroStack.length - 1];

                debug(`Line ${lineNumber} Peeked ${identifier}`);

                if (!identifier) {
                    rl.off('line', lineHandler);
                    reject(new Error(`Macro stack is empty handling #else on line ${lineNumber}`));
                    return;
                }

                if (identifier.indexOf('NAPI_EXPERIMENTAL') > -1) {
                    const lastMode = mode[mode.length - 1];
                    mode[mode.length - 1] = (lastMode === 'ignore') ? 'write' : 'ignore';
                    return;
                }
            }
            else if (line.match(/^\s*#endif(?:\s+|$)/)) {
                const identifier = macroStack.pop();
                mode.pop();

                debug(`Line ${lineNumber} Popped ${identifier}`);

                if (!identifier) {
                    rl.off('line', lineHandler);
                    reject(new Error(`Macro stack is empty handling #endif on line ${lineNumber}`));
                    return;
                }

                if (identifier.indexOf('NAPI_EXPERIMENTAL') > -1) {
                    return;
                }
            }

            if (mode.length === 0) {
                rl.off('line', lineHandler);
                reject(new Error(`Write mode empty handling #endif on line ${lineNumber}`));
                return;
            }

            if (mode[mode.length - 1] === 'write') {
                toWrite += `${line}\n`;
            } else if (mode[mode.length - 1] === 'preprocessor') {
                if (!preprocessor) {
                    reject(new Error(`Preprocessor mode without preprocessor on line ${lineNumber}`));
                    return;
                }

                if (line.endsWith('\\')) {
                    preprocessor.push(line.substring(0, line.length - 1));
                    return;
                }

                preprocessor.push(line);

                const expression = preprocessor.join('');
                preprocessor.length = 0;
                mode.pop();

                if (!handlePreprocessor(expression)) {
                    return;
                }
            }

        });

        rl.on('close', () => {
            if (macroStack.length > 0) {
                reject(new Error(`Macro stack is not empty at EOF: ${inspect(macroStack)}`));
            }
            else if (mode.length > 1) {
                reject(new Error(`Write mode greater than 1 at EOF: ${inspect(mode)}`));
            }
            else if (toWrite.match(/^\s*#if(?:n)?def\s+NAPI_EXPERIMENTAL/m)) {
                reject(new Error(`Output has match for NAPI_EXPERIMENTAL`));
            }
            else {
                resolve(writeFile(destination, toWrite));
            }
        });
    });
}

/**
 * Validate syntax for a file using clang.
 * @param {string} path Path for file to validate with clang.
 */
async function validateSyntax(path) {
    try {
        await runClang(['-fsyntax-only', path]);
    } catch (e) {
        throw new Error(`Syntax validation failed for ${path}: ${e}`);
    }
}

async function main() {
    const { values: { tag, verbose } } = parseArgs({
        options: {
            tag: {
                type: 'string',
                short: 't',
                default: await getLatestReleaseVersion()
            },
            verbose: {
                type: 'boolean',
                short: 'v',
            },
        },
    });

    console.log(`feat: update headers from nodejs/node tag ${tag}`);

    const files = ['js_native_api_types.h', 'js_native_api.h', 'node_api_types.h', 'node_api.h'];

    for (const filename of files) {
        const url = `https://raw.githubusercontent.com/nodejs/node/${tag}/src/${filename}`;
        const path = resolve(__dirname, '..', 'include', filename);

        if (verbose) {
            console.log(`  ${url} -> ${path}`);
        }

        const response = await fetch(url);
        if (!response.ok) {
            throw new Error(`Fetch of ${url} returned ${response.status} ${response.statusText}`);
        }

        await removeExperimentals(Readable.fromWeb(response.body), path, verbose);

        await validateSyntax(path);
    }
}

main().catch(e => {
    console.error(e);
    process.exitCode = 1;
});
