const MinifyHTML = require('@minify-html/node')
const UglifyJS = require('uglify-js')
const CleanCss = require('clean-css')
const Zlib = require('zlib')
const fs = require('fs')
const path = require('path')

const input_dir = "/deploy/in"
const output_dir = "/deploy/out"

function ensureDirectoryExists(file_path) {
    const file_dir = path.dirname(file_path)
    if (!fs.existsSync(file_dir)) {
        fs.mkdirSync(file_dir)
    }
}

function minifyHtml(input_file, output_file) {
    const opts = {keep_spaces_between_attributes: true, keep_comments: true}
    const minified = MinifyHTML.minify(fs.readFileSync(input_file), opts)
    ensureDirectoryExists(output_file)
    fs.writeFileSync(output_file, minified)
}

function minifyCss(input_file, output_file) {
    input = fs.readFileSync(input_file)
    const output = new CleanCss().minify(input)
    fs.writeFileSync(output_file, output.styles)
}

function minifyJs(input_file, output_file) {
    const input = fs.readFileSync(input_file, 'utf8')
    const minified = UglifyJS.minify(input)
    fs.writeFileSync(output_file, minified.code, 'utf8')
}

function minifyJson(input_file, output_file) {
    const json = fs.readFileSync(input_file, 'utf8')
    const parsed = JSON.parse(json)
    const minified = JSON.stringify(parsed)
    fs.writeFileSync(output_file, minified, 'utf8')
}

function minifyXml(input_file, output_file) {
    // Not yet available
}

function compressGzip(input_path, output_path) {
    const input = fs.createReadStream(input_path)
    const gzip = Zlib.createGzip()
    const output = fs.createWriteStream(output_path)
    input.pipe(gzip).pipe(output)
    output.on('finish', () => {
        return
    })
}

function compressBrotli(input_path, output_path) {
    const input = fs.createReadStream(input_path)
    const brotli = Zlib.createBrotliCompress()
    const output = fs.createWriteStream(output_path)
    input.pipe(brotli).pipe(output)
    output.on('finish', () => {
        return
    })
}

processable_extentions = ['.html', '.css', '.js', '.json', '.xml', '.log', '.md', '.svg', '.wasm', '.yaml', '.yml', '.vcard', '.ical']

// Loop over file and subdirectories

function processFiles(inputDir, outputDir) {
    fs.readdirSync(inputDir).forEach(file => {
        const inputFile = path.join(inputDir, file);
        const outputFile = path.join(outputDir, file);

        if (fs.statSync(inputFile).isDirectory()) {
            const nestedOutputDir = path.join(outputDir, file);
            fs.mkdirSync(nestedOutputDir, { recursive: true });
            processFiles(inputFile, nestedOutputDir); // Recursive call with nested input and output directories
        } else {
            const extension = path.extname(file).toLowerCase();
            switch (extension) {
                case '.html':
                    minifyHtml(inputFile, outputFile);
                    break;
                case '.css':
                    minifyCss(inputFile, outputFile);
                    break;
                case '.js':
                    minifyJs(inputFile, outputFile);
                    break;
                case '.json':
                    minifyJson(inputFile, outputFile);
                    break;
                case '.xml':
                    minifyXml(inputFile, outputFile);
                    break;
                default:
                    fs.copyFileSync(inputFile, outputFile);
            }
        }
    });
}

function compressFiles(directory) {
    fs.readdirSync(directory).forEach(file => {
        const file_path = path.join(directory, file);

        if (fs.statSync(file_path).isDirectory()) {
            compressFiles(file_path);
        } else {
            const extension = path.extname(file).toLowerCase();
            if (processable_extentions.includes(extension)) {
                compressGzip(file_path, file_path + '.gz');
                compressBrotli(file_path, file_path + '.br');
            }
        }
    });
}

processFiles(input_dir, output_dir);
compressFiles(output_dir);