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

import promises from "node:fs/promises";
import path from "node:path";
import Datastore from "@seald-io/nedb";

/**
 * 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 };

    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<Array<unknown>>} A promise that resolves to an array of the documents in the pack file
 */
function convertPackFileToJSON(filename) {
    const db = new Datastore({ filename, autoload: true });
    return new Promise((resolve, reject) => {
        db.find({}, (err, docs) => {
            if (err) {
                reject(err);
            } else {
                resolve(
                    JSON.stringify(
                        docs.map((entry) => cleanPackEntry(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);
}