import { BooleanOption, EnumOption, StringOption, getOptionValues, } from "../../RendererOptions/index.js";
import { assertNever } from "../../support/Support.js";
import { TargetLanguage } from "../../TargetLanguage.js";
import { NewtonsoftCSharpRenderer } from "./NewtonSoftCSharpRenderer.js";
import { SystemTextJsonCSharpRenderer } from "./SystemTextJsonCSharpRenderer.js";
import { needTransformerForType } from "./utils.js";
export const cSharpOptions = {
    framework: new EnumOption("framework", "Serialization framework", {
        NewtonSoft: "NewtonSoft",
        SystemTextJson: "SystemTextJson",
    }, "NewtonSoft"),
    useList: new EnumOption("array-type", "Use T[] or List<T>", {
        array: false,
        list: true,
    }, "array"),
    dense: new EnumOption("density", "Property density", {
        normal: false,
        dense: true,
    }, "normal", "secondary"),
    // FIXME: Do this via a configurable named eventually.
    namespace: new StringOption("namespace", "Generated namespace", "NAME", "QuickType"),
    version: new EnumOption("csharp-version", "C# version", {
        "5": 5,
        "6": 6,
    }, "6", "secondary"),
    virtual: new BooleanOption("virtual", "Generate virtual properties", false),
    typeForAny: new EnumOption("any-type", 'Type to use for "any"', {
        object: "object",
        dynamic: "dynamic",
    }, "object", "secondary"),
    useDecimal: new EnumOption("number-type", "Type to use for numbers", {
        double: false,
        decimal: true,
    }, "double", "secondary"),
    features: new EnumOption("features", "Output features", {
        complete: { namespaces: true, helpers: true, attributes: true },
        "attributes-only": {
            namespaces: true,
            helpers: false,
            attributes: true,
        },
        "just-types-and-namespace": {
            namespaces: true,
            helpers: false,
            attributes: false,
        },
        "just-types": {
            namespaces: true,
            helpers: false,
            attributes: false,
        },
    }, "complete"),
    baseclass: new EnumOption("base-class", "Base class", {
        EntityData: "EntityData",
        Object: undefined,
    }, "Object", "secondary"),
    checkRequired: new BooleanOption("check-required", "Fail if required properties are missing", false),
    keepPropertyName: new BooleanOption("keep-property-name", "Keep original field name generate", false),
};
export const newtonsoftCSharpOptions = Object.assign({}, cSharpOptions, {});
export const systemTextJsonCSharpOptions = Object.assign({}, cSharpOptions, {});
export const cSharpLanguageConfig = {
    displayName: "C#",
    names: ["cs", "csharp"],
    extension: "cs",
};
export class CSharpTargetLanguage extends TargetLanguage {
    constructor() {
        super(cSharpLanguageConfig);
    }
    getOptions() {
        return cSharpOptions;
    }
    get stringTypeMapping() {
        const mapping = new Map();
        mapping.set("date", "date-time");
        mapping.set("time", "date-time");
        mapping.set("date-time", "date-time");
        mapping.set("uuid", "uuid");
        mapping.set("uri", "uri");
        mapping.set("integer-string", "integer-string");
        mapping.set("bool-string", "bool-string");
        return mapping;
    }
    get supportsUnionsWithBothNumberTypes() {
        return true;
    }
    get supportsOptionalClassProperties() {
        return true;
    }
    needsTransformerForType(t) {
        const need = needTransformerForType(t);
        return need !== "none" && need !== "nullable";
    }
    makeRenderer(renderContext, untypedOptionValues) {
        const options = getOptionValues(cSharpOptions, untypedOptionValues);
        switch (options.framework) {
            case "NewtonSoft":
                return new NewtonsoftCSharpRenderer(this, renderContext, getOptionValues(newtonsoftCSharpOptions, untypedOptionValues));
            case "SystemTextJson":
                return new SystemTextJsonCSharpRenderer(this, renderContext, getOptionValues(systemTextJsonCSharpOptions, untypedOptionValues));
            default:
                return assertNever(options.framework);
        }
    }
}
