/**
 * Metadata management CLI tool.
 * @author Louis-Dominique Dubeau
 * @license MPL 2.0
 * @copyright Mangalam Research Center for Buddhist Languages
 */
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
    result["default"] = mod;
    return result;
};
define(["require", "exports", "ajv", "argparse", "fs", "js-yaml", "path", "../modes/generic/doc-pattern", "../modes/generic/metadata-schema.json", "../util"], function (require, exports, ajv_1, argparse_1, fs, yaml, path, doc_pattern_1, metadata_schema_json_1, util_1) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    ajv_1 = __importDefault(ajv_1);
    fs = __importStar(fs);
    yaml = __importStar(yaml);
    path = __importStar(path);
    metadata_schema_json_1 = __importDefault(metadata_schema_json_1);
    // tslint:disable-next-line:completed-docs
    class Fatal extends Error {
        constructor(msg) {
            super(msg);
            this.name = "Fatal";
            this.message = msg;
            util_1.fixPrototype(this, Fatal);
        }
    }
    const prog = path.basename(process.argv[1]);
    // tslint:disable-next-line:no-any
    process.on("uncaughtException", (ex) => {
        if (ex instanceof Fatal) {
            process.stderr.write(`${prog}: ${ex.message}\n`);
            process.exit(1);
        }
        else {
            throw ex;
        }
    });
    //
    // Actual logic
    //
    function fileAsString(p) {
        return fs.readFileSync(path.resolve(p), "utf8").toString();
    }
    // tslint:disable-next-line:no-any
    function parseFile(name, data) {
        let ret;
        try {
            ret = JSON.parse(data);
        }
        // tslint:disable-next-line:no-empty
        catch (ex) { }
        if (ret !== undefined) {
            return ret;
        }
        try {
            ret = yaml.safeLoad(data, {
                schema: yaml.JSON_SCHEMA,
            });
        }
        // tslint:disable-next-line:no-empty
        catch (ex) { }
        if (ret !== undefined) {
            return ret;
        }
        throw new Fatal(`cannot parse ${name}`);
    }
    const parser = new argparse_1.ArgumentParser({
        addHelp: true,
        description: "Generates a JSON file suitable for using as the " +
            "``metadata`` option for a generic Meta object. The input file must " +
            "be a JSON file in the format produced by TEI's odd2json.xsl " +
            "transformation.",
    });
    parser.addArgument(["input"], { help: "Input file." });
    parser.addArgument(["output"], {
        help: "Output file. If absent, outputs to stdout.",
        nargs: "?",
    });
    parser.addArgument(["--tei"], {
        help: "Treat the input as a TEI JSON file produced by TEI's odd2json.xsl.",
        action: "storeTrue",
    });
    parser.addArgument(["-p", "--pretty"], {
        help: "Pretty print the final JSON.",
        action: "storeTrue",
    });
    parser.addArgument(["--merge"], {
        help: "Add a file to shallow merge with the generated output.",
        action: "append",
        defaultValue: [],
    });
    const args = parser.parseArgs();
    const output = {
        generator: prog,
        date: new Date().toISOString(),
        version: "2",
    };
    if (args.tei) {
        const inputData = fileAsString(args.input);
        const parsed = parseFile(args.input, inputData);
        output.namespaces = {
            // tslint:disable-next-line:no-http-string
            "": "http://www.tei-c.org/ns/1.0",
        };
        const { elements: inputElements } = parsed;
        for (let i = inputElements.length - 1; i >= 0; i--) {
            // Delete class specs
            if (inputElements[i].type !== "elementSpec") {
                inputElements.splice(i, 1);
            }
        }
        const elements = [];
        for (const el of inputElements) {
            elements.push({
                name: el.ident,
                desc: el.shortDesc,
                ns: el.ns,
            });
        }
        output.elements = elements;
    }
    else {
        if (args.merge === undefined) {
            args.merge = [args.input];
        }
        else {
            args.merge.unshift(args.input);
        }
    }
    for (const toMerge of args.merge) {
        const data = fileAsString(toMerge);
        const parsedMerge = parseFile(toMerge, data);
        if (parsedMerge.version !== "2") {
            throw new Fatal("files must follow metadata version 2");
        }
        if (parsedMerge.generator !== undefined || parsedMerge.date !== undefined) {
            throw new Error("generator or date in a file consumed by this tool is invalid");
        }
        if (parsedMerge.namespaces !== undefined &&
            parsedMerge.namespaces.xml !== undefined) {
            throw new Error("trying to set the xml namespace");
        }
        // tslint:disable-next-line:forin
        for (const key in parsedMerge) {
            // tslint:disable-next-line:no-any
            output[key] = parsedMerge[key];
        }
    }
    const ajv = new ajv_1.default();
    const validator = ajv.compile(metadata_schema_json_1.default);
    const valid = validator(output);
    if (!valid) {
        if (validator.errors != null) {
            for (const error of validator.errors) {
                // tslint:disable-next-line:no-console
                console.log(error);
            }
        }
        throw new Fatal("output is not valid");
    }
    if (output.dochtml !== undefined) {
        if (output.dochtml.method === "simple-pattern") {
            doc_pattern_1.compile(output.dochtml.pattern);
        }
        else {
            throw new Fatal(`unknown method: ${output.dochtml.method}`);
        }
    }
    const stringified = JSON.stringify(output, undefined, args.pretty ? 2 : undefined);
    if (args.output !== undefined) {
        fs.writeFileSync(args.output, stringified);
    }
    else {
        // tslint:disable-next-line:no-console
        console.log(stringified);
    }
});
//  LocalWords:  CLI MPL uncaughtException utf TEI's json xsl stdout tei
//  LocalWords:  storeTrue elementSpec
//# sourceMappingURL=wed-metadata.js.map