import { Base64 } from "js-base64";
import pako from "pako";
import * as YAML from "yaml";
import { messageError } from "../Messages.js";
export function isStringMap(x, checkValue) {
    if (typeof x !== "object" || Array.isArray(x) || x === null) {
        return false;
    }
    if (checkValue !== undefined) {
        for (const k of Object.getOwnPropertyNames(x)) {
            const v = x[k];
            if (!checkValue(v)) {
                return false;
            }
        }
    }
    return true;
}
export function checkString(x) {
    return typeof x === "string";
}
export function checkStringMap(x, checkValue) {
    if (checkValue && isStringMap(x, checkValue)) {
        return x;
    }
    if (isStringMap(x)) {
        return x;
    }
    return panic(`Value must be an object, but is ${x}`);
}
export function checkArray(x, checkItem) {
    if (!Array.isArray(x)) {
        return panic(`Value must be an array, but is ${x}`);
    }
    if (checkItem !== undefined) {
        for (const v of x) {
            if (!checkItem(v)) {
                return panic(`Array item does not satisfy constraint: ${v}`);
            }
        }
    }
    return x;
}
export function defined(x) {
    if (x !== undefined)
        return x;
    return panic("Defined value expected, but got undefined");
}
export function nonNull(x) {
    if (x !== null)
        return x;
    return panic("Non-null value expected, but got null");
}
export function assertNever(x) {
    return messageError("InternalError", { message: `Unexpected object ${x}` });
}
export function assert(condition, message = "Assertion failed") {
    if (!condition) {
        return messageError("InternalError", { message });
    }
}
export function panic(message) {
    return messageError("InternalError", { message });
}
export function mustNotHappen() {
    return panic("This must not happen");
}
export function repeated(n, value) {
    const arr = [];
    for (let i = 0; i < n; i++) {
        arr.push(value);
    }
    return arr;
}
export function repeatedCall(n, producer) {
    const arr = [];
    for (let i = 0; i < n; i++) {
        arr.push(producer());
    }
    return arr;
}
export function errorMessage(e) {
    if (e instanceof Error) {
        return e.message;
    }
    return e.toString();
}
export function inflateBase64(encoded) {
    const bytes = Base64.atob(encoded);
    return pako.inflate(bytes, { to: "string" });
}
export function parseJSON(text, description, address = "<unknown>") {
    try {
        // https://gist.github.com/pbakondy/f5045eff725193dad9c7
        if (text.charCodeAt(0) === 0xfeff) {
            text = text.slice(1);
        }
        return YAML.parse(text);
    }
    catch (e) {
        let message;
        if (e instanceof SyntaxError) {
            message = e.message;
        }
        else {
            message = `Unknown exception ${e}`;
        }
        return messageError("MiscJSONParseError", {
            description,
            address,
            message,
        });
    }
}
export function indentationString(level) {
    return "  ".repeat(level);
}
// FIXME: fix this enum iteration
export function numberEnumValues(e) {
    const result = [];
    for (const k of Object.keys(e)) {
        const v = e[k];
        if (typeof v === "number") {
            result.push(v);
        }
    }
    return result;
}
