/**
 * Copyright (c) Microsoft Corporation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// @ts-check
const xml2js = require('xml2js');
const fs = require('fs');
const path = require('path');
const { argv } = require('process');

// From https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/ui/prefs/prefs_tab_helper.cc;l=130;drc=62b77bef90de54f0136b51935fa2d5814a1b4da9
// and https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/platform/text/locale_to_script_mapping.cc;l=44;drc=befcb6de95fb8c88c162ce1f64111f6c17351b13
// note that some suffixes like _JAPANESE, _KOREAN don't have matching icu codes.
const codeToScriptName = new Map([
    ['ARABIC', 'arab'],
    ['CYRILLIC', 'cyrl'],
    ['GREEK', 'grek'],
    ['JAPANESE', 'jpan'],
    ['KOREAN', 'hang'],
    ['SIMPLIFIED_HAN', 'hans'],
    ['TRADITIONAL_HAN', 'hant'],
]);

const idToProtocol = new Map([
    ['IDS_STANDARD_FONT_FAMILY', 'standard'],
    ['IDS_SANS_SERIF_FONT_FAMILY','sansSerif'],
    ['IDS_SERIF_FONT_FAMILY', 'serif'],
    ['IDS_CURSIVE_FONT_FAMILY', 'cursive'],
    ['IDS_FANTASY_FONT_FAMILY', 'fantasy'],
    ['IDS_FIXED_FONT_FAMILY', 'fixed'],
]);

class ScriptFontFamilies {
    scriptToFontFamilies = new Map();

    setFont(scriptName, familyName, value) {
        let fontFamilies = this.scriptToFontFamilies.get(scriptName);
        if (!fontFamilies) {
            fontFamilies = {};
            this.scriptToFontFamilies.set(scriptName, fontFamilies);
        }
        fontFamilies[familyName] = value;
    }

    toJSON() {
        const forScripts = Array.from(this.scriptToFontFamilies.entries()).filter(([name, _]) => !!name).map(([script, fontFamilies]) => ({ script, fontFamilies }));
        return {
            fontFamilies: this.scriptToFontFamilies.get(''),
            forScripts: forScripts.length ? forScripts : undefined
        };
    }
}

if (argv.length < 3)
    throw new Error('Expected path to "chromium/src" checkout as first argument')

// Upstream files location is https://chromium.googlesource.com/chromium/src/+/main/chrome/app/resources/locale_settings_linux.grd
const resourceDir = path.join(argv[2], 'chrome/app/resources/');
if (!fs.existsSync(resourceDir))
    throw new Error(`Path ${resourceDir} does not exist`);

function parseXML(xml) {
    let result;
    xml2js.parseString(xml, {trim: true}, (err, r) => result = r);
    return result;
}

const result = {};
for (const platform of ['linux', 'mac', 'win']) {
    const f = path.join(resourceDir, `locale_settings_${platform}.grd`);
    const xmlDataStr = fs.readFileSync(f);
    let jsonObj = parseXML(xmlDataStr);
    if (!jsonObj)
        throw new Error('Failed to parse ' + f);
    const fontFamilies = new ScriptFontFamilies();
    const defaults = jsonObj.grit.release[0].messages[0].message;
    defaults.forEach(e => {
        const name = e['$']['name'];
        let scriptName = '';
        let familyName;
        for (const id of idToProtocol.keys()) {
            if (!name.startsWith(id))
                continue;
            familyName = idToProtocol.get(id);
            if (name !== id) {
                const suffix = name.substring(id.length + 1);
                // We don't support this, see https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/ui/prefs/prefs_tab_helper.cc;l=384-390;drc=62b77bef90de54f0136b51935fa2d5814a1b4da9
                if (suffix === 'ALT_WIN')
                    continue;
                scriptName = codeToScriptName.get(suffix);
                if (!scriptName)
                    throw new Error('NO Script name for: ' + suffix);
            }
            break;
        }
        // Skip things like IDS_NTP_FONT_FAMILY, IDS_MINIMUM_FONT_SIZE etc.
        if (!familyName)
            return;
        fontFamilies.setFont(scriptName, familyName, e['_'])
    });
    result[platform] = fontFamilies.toJSON();
}

console.log(JSON.stringify(result, null, 2).replaceAll('"', `'`));