const fs = require('fs');
const path = require('path');
const readline = require('readline');
const utils = require('./utils.js');

exports.process = async function(root, options) {
    const macroPrefix = options.prefix || '#';
    const entryPoint = options.entry || '';

    root = fs.realpathSync(root);

    const included = [];

    const processFile = async function(fileName) {
        const fullPath = path.join(root, fileName);
        if(included.includes(fullPath))
            return '';
        included.push(fullPath);

        if(!fullPath.startsWith(root))
            return '/* *** INVALID PATH: ' + fullPath + ' */';
        if(!fs.existsSync(fullPath))
            return '/* *** FILE NOT FOUND: ' + fullPath + ' */';

        const lines = readline.createInterface({
            input: fs.createReadStream(fullPath),
            crlfDelay: Infinity,
        });

        let output = '';
        let lastWasEmpty = false;

        if(options.showPath)
            output += "/* *** PATH: " + fullPath + " */\n";

        for await(const line of lines) {
            const lineTrimmed = utils.trim(line);
            if(lineTrimmed === '')
                continue;

            if(line.startsWith(macroPrefix)) {
                const args = lineTrimmed.split(' ');
                const macro = utils.trim(utils.trimStart(args.shift(), macroPrefix));

                switch(macro) {
                    case 'comment':
                        break;

                    case 'include': {
                        const includePath = utils.trimEnd(args.join(' '), ';');
                        output += utils.trim(await processFile(includePath));
                        output += "\n";
                        break;
                    }

                    case 'buildvars':
                        if(typeof options.buildVars === 'object') {
                            const bvTarget = options.buildVarsTarget || 'window';
                            const bvProps = [];

                            for(const bvName in options.buildVars)
                                bvProps.push(`${bvName}: { value: ${JSON.stringify(options.buildVars[bvName])} }`);

                            if(Object.keys(bvProps).length > 0)
                                output += `Object.defineProperties(${bvTarget}, { ${bvProps.join(', ')} });\n`;
                        }
                        break;

                    default:
                        output += line;
                        output += "\n";
                        break;
                }
            } else {
                output += line;
                output += "\n";
            }
        }

        return output;
    };

    return await processFile(entryPoint);
};

exports.housekeep = function(assetsPath) {
    const files = fs.readdirSync(assetsPath).map(fileName => {
        const stats = fs.statSync(path.join(assetsPath, fileName));
        return {
            name: fileName,
            lastMod: stats.mtimeMs,
        };
    }).sort((a, b) => b.lastMod - a.lastMod).map(info => info.name);

    const regex = /^(.+)[\-\.]([a-f0-9]+)\.(.+)$/i;
    const counts = {};

    for(const fileName of files) {
        const match = fileName.match(regex);
        if(match) {
            const name = match[1] + '-' + match[3];
            counts[name] = (counts[name] || 0) + 1;

            if(counts[name] > 5)
                fs.unlinkSync(path.join(assetsPath, fileName));
        } else console.log(`Encountered file name in assets folder with unexpected format: ${fileName}`);
    }
};