const fs = require("fs");

const suspicious = /[ÃÂØÙÐÑâäæà¤]/g;

function score(value) {
    return (value.match(suspicious) || []).length;
}

const windows1252 = new Map([
    [0x20ac, 0x80], [0x201a, 0x82], [0x0192, 0x83], [0x201e, 0x84], [0x2026, 0x85],
    [0x2020, 0x86], [0x2021, 0x87], [0x02c6, 0x88], [0x2030, 0x89], [0x0160, 0x8a],
    [0x2039, 0x8b], [0x0152, 0x8c], [0x017d, 0x8e], [0x2018, 0x91], [0x2019, 0x92],
    [0x201c, 0x93], [0x201d, 0x94], [0x2022, 0x95], [0x2013, 0x96], [0x2014, 0x97],
    [0x02dc, 0x98], [0x2122, 0x99], [0x0161, 0x9a], [0x203a, 0x9b], [0x0153, 0x9c],
    [0x017e, 0x9e], [0x0178, 0x9f]
]);

function encodeWindows1252(value) {
    const bytes = [];
    for (const char of value) {
        const code = char.codePointAt(0);
        if (code <= 0xff) bytes.push(code);
        else if (windows1252.has(code)) bytes.push(windows1252.get(code));
        else return null;
    }
    return Buffer.from(bytes);
}

function repairLine(line) {
    let current = line;
    for (let pass = 0; pass < 3; pass += 1) {
        if (!score(current)) break;
        const encoded = encodeWindows1252(current);
        if (!encoded) break;
        const candidate = encoded.toString("utf8");
        if (candidate.includes("�") || score(candidate) >= score(current)) break;
        current = candidate;
    }
    return current;
}

for (const file of process.argv.slice(2)) {
    const source = fs.readFileSync(file, "utf8");
    const fixed = source.split(/(?<=\n)/).map(repairLine).join("");
    fs.writeFileSync(file, fixed, "utf8");
    process.stdout.write(`${file}: repaired ${score(source) - score(fixed)} suspicious sequences\n`);
}
