// SPDX-FileCopyrightText: 2021 Johannes Loher
//
// SPDX-License-Identifier: MIT

import promises from "node:fs/promises";
import path from "node:path";

/**
 * Removes unwanted data from a pack entry
 */
function cleanPackEntry(entry, cleanSourceId = true) {
    if (cleanSourceId) {
        delete entry.flags?.core?.sourceId;
    }
    Object.keys(entry.flags).forEach((scope) => {
        if (Object.keys(entry.flags[scope]).length === 0) {
            delete entry.flags[scope];
        }
    });
    if (entry.permission) entry.permission = { default: 0 };
    if (entry._stats?.lastModifiedBy) entry._stats.lastModifiedBy = "DS4BuildSystem00";

    const embeddedDocumentCollections = [
        "drawings",
        "effects",
        "items",
        "lights",
        "notes",
        "results",
        "sounds",
        "templates",
        "tiles",
        "tokens",
        "walls",
    ];
    embeddedDocumentCollections
        .flatMap((embeddedDocumentCollection) => entry[embeddedDocumentCollection] ?? [])
        .forEach((embeddedEntry) => cleanPackEntry(embeddedEntry, false));
    return entry;
}

/**
 * Converts JSON content containing an array to a Pack (NeDB) string.
 * @param {string | ArrayBuffer} contents   The input JSON content
 * @returns {Promise<string>} The resulting Pack string
 */
export async function convertJSONToPack(contents) {
    const jsonString = contents.toString();
    return (
        JSON.parse(jsonString)
            .map((entry) => cleanPackEntry(entry))
            .map((entry) => JSON.stringify(entry))
            .join("\n") + "\n"
    );
}

/**
 * Converts a pack file (NeDB) to a JSON string.
 * @param {string} filename The name of the pack file
 * @returns {Promise<string>} A promise that resolves to JSON string representing the pack file
 */
async function convertPackFileToJSON(filename) {
    const data = await promises.readFile(filename, { flag: "r", encoding: "utf-8" });
    return (
        JSON.stringify(
            data.split(/\r?\n/).flatMap((entry) => {
                if (entry === "") return [];
                return cleanPackEntry(JSON.parse(entry));
            }),
            undefined,
            4,
        ) + "\n"
    );
}

/**
 * Converts a pack file (NeDB) to a JSON file and puts it in the given directory. If no directory is given, it is put
 * into the same directory as the pack file.
 * @param {string} filename The name of the pack file
 * @param {string} [directory] A directory to put the json file into
 * @returns {Promise<void>} A promise that resolves once the JSON file has been written
 */
export async function convertPackFileToJSONFile(filename, directory) {
    if (directory === undefined) {
        directory = path.dirname(filename);
    }
    console.log("  ", path.basename(filename));
    const jsonFilePath = path.join(directory, `${path.basename(filename, path.extname(filename))}.json`);
    const json = await convertPackFileToJSON(filename);
    await promises.writeFile(jsonFilePath, json);
}