"use strict";
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.NewPrimitive = exports.popTempVar = exports.pushTempVar = void 0;
const codemodel_v3_1 = require("@azure-tools/codemodel-v3");
const codegen_1 = require("@azure-tools/codegen");
const codegen_csharp_1 = require("@azure-tools/codegen-csharp");
const codegen_csharp_2 = require("@azure-tools/codegen-csharp");
const codegen_csharp_3 = require("@azure-tools/codegen-csharp");
const codegen_csharp_4 = require("@azure-tools/codegen-csharp");
const codegen_csharp_5 = require("@azure-tools/codegen-csharp");
const clientruntime_1 = require("../clientruntime");
let tmpVar;
let max = 0;
function numToChars(ch) {
    if (ch < 26) {
        return String.fromCharCode(122 - ch);
    }
    return `_${numToChars(ch - 26)}`;
}
function pushTempVar() {
    if (!tmpVar) {
        tmpVar = 1;
        max = 1;
    }
    else {
        tmpVar++;
        max++;
    }
    return `__${numToChars(max)}`;
}
exports.pushTempVar = pushTempVar;
function popTempVar() {
    if (tmpVar) {
        tmpVar--;
    }
    if (tmpVar === 0) {
        tmpVar = undefined;
        max = 0;
    }
}
exports.popTempVar = popTempVar;
class NewPrimitive {
    get isNullable() {
        return !this.isRequired;
    }
    get encode() {
        return (this.schema.extensions && this.schema.extensions['x-ms-skip-url-encoding']) ? '' : 'global::System.Uri.EscapeDataString';
    }
    get defaultOfType() {
        return (0, codegen_csharp_3.toExpression)(`default(${this.declaration})`);
    }
    get convertObjectMethod() {
        const v = pushTempVar();
        const result = `(${v})=> (${this.baseType}) global::System.Convert.ChangeType(${v}, typeof(${this.baseType}))`;
        popTempVar();
        return result;
    }
    constructor(schema) {
        this.schema = schema;
    }
    /** validatePresence on primitives is generally not required; the nullability determines requiredness... */
    validatePresence(eventListener, property) {
        return '';
    }
    get baseType() {
        return this.declaration.replace('?', '');
    }
    castJsonTypeToPrimitive(tmpValue, defaultValue) {
        return `(${this.declaration})${tmpValue}`;
    }
    castXmlTypeToPrimitive(tmpValue, defaultValue) {
        return `(${this.declaration})${tmpValue}`;
    }
    deserializeFromContainerMember(mediaType, container, serializedName, defaultValue) {
        switch (mediaType) {
            case codemodel_v3_1.KnownMediaType.Json: {
                // JsonObject
                const tmp = `__${(0, codegen_1.camelCase)(['json', ...(0, codegen_1.deconstruct)(serializedName)])}`;
                return (0, codegen_csharp_3.toExpression)(`If( ${(0, codegen_csharp_3.valueOf)(container)}?.PropertyT<${this.jsonType}>("${serializedName}"), out var ${tmp}) ? ${this.castJsonTypeToPrimitive(tmp, defaultValue.value)} : ${defaultValue}`);
            }
            case codemodel_v3_1.KnownMediaType.Xml: {
                // XElement/XElement or XElement/XAttribute
                const tmp = `__${(0, codegen_1.camelCase)(['xml', ...(0, codegen_1.deconstruct)(serializedName)])}`;
                return (0, codegen_csharp_3.toExpression)(this.isXmlAttribute ?
                    `If( ${(0, codegen_csharp_3.valueOf)(container)}?.Attribute("${serializedName}"), out var ${tmp}) ? ${this.castXmlTypeToPrimitive(tmp, defaultValue.value)} : ${defaultValue}` :
                    `If( ${(0, codegen_csharp_3.valueOf)(container)}?.Element("${serializedName}"), out var ${tmp}) ? ${this.castXmlTypeToPrimitive(tmp, defaultValue.value)} : ${defaultValue}`);
            }
            case codemodel_v3_1.KnownMediaType.Header: {
                // HttpResponseHeaders
                const tmp = `__${(0, codegen_1.camelCase)(['header', ...(0, codegen_1.deconstruct)(serializedName)])}`;
                return (0, codegen_csharp_3.toExpression)(`System.Linq.Enumerable.FirstOrDefault(${serializedName}) is string ${tmp} ? ${this.baseType}.TryParse( ${tmp}, out ${this.baseType} ${tmp}Value ) ? ${tmp}Value : ${defaultValue} : ${defaultValue}`);
            }
        }
        return (0, codegen_csharp_3.toExpression)(`${defaultValue} /* deserializeFromContainerMember doesn't support '${mediaType}' ${__filename} */`);
    }
    deserializeFromNode(mediaType, node, defaultValue) {
        try {
            const tmp = pushTempVar();
            switch (mediaType) {
                case codemodel_v3_1.KnownMediaType.Json:
                    // node should be a json type
                    return (0, codegen_csharp_3.toExpression)(`${node} is ${this.jsonType} ${tmp} ? ${this.castJsonTypeToPrimitive(tmp, defaultValue.value)} : ${defaultValue}`);
                case codemodel_v3_1.KnownMediaType.Xml:
                    // XElement or XAttribute
                    return (0, codegen_csharp_3.toExpression)(this.isXmlAttribute ?
                        `${node} is ${codegen_csharp_2.System.Xml.Linq.XAttribute} ${tmp} ? ${this.castXmlTypeToPrimitive(tmp, defaultValue.value)} : ${defaultValue}` :
                        `${node} is ${codegen_csharp_2.System.Xml.Linq.XElement} ${tmp} ? ${this.castXmlTypeToPrimitive(tmp, defaultValue.value)}: ${defaultValue}`);
            }
        }
        finally {
            popTempVar();
        }
        return (0, codegen_csharp_3.toExpression)(`null /* deserializeFromContainer doens't support '${mediaType}' ${__filename}*/`);
    }
    /** emits an expression to deserialize content from a string */
    deserializeFromString(mediaType, content, defaultValue) {
        try {
            const tmp = pushTempVar();
            switch (mediaType) {
                case codemodel_v3_1.KnownMediaType.UriParameter: {
                    return (0, codegen_csharp_3.toExpression)(`${this.baseType}.TryParse( ${(0, codegen_csharp_3.valueOf)(content)}, out ${this.baseType} ${tmp} ) ? ${tmp} : ${defaultValue}`);
                }
            }
        }
        finally {
            popTempVar();
        }
        return (0, codegen_csharp_3.toExpression)(`null /* deserializeFromString doesn't support '${mediaType}' ${__filename}`);
    }
    /** emits an expression to deserialize content from a content/response */
    deserializeFromResponse(mediaType, content, defaultValue) {
        switch (mediaType) {
            case codemodel_v3_1.KnownMediaType.Json:
                return (0, codegen_csharp_3.toExpression)(`${content}.Content.ReadAsStringAsync().ContinueWith( body => (${this.baseType}) global::System.Convert.ChangeType(body.Result, typeof(${this.baseType})))`);
        }
        return (0, codegen_csharp_3.toExpression)(`null /* deserializeFromResponse doesn't support '${mediaType}' ${__filename}*/`);
    }
    /** emits an expression serialize this to a HttpContent */
    serializeToContent(mediaType, value, mode) {
        return (0, codegen_csharp_3.toExpression)(`null /* serializeToContent doesn't support '${mediaType}' ${__filename}*/`);
    }
    serializeToNode(mediaType, value, serializedName, mode) {
        switch (mediaType) {
            case codemodel_v3_1.KnownMediaType.Json:
                return this.isRequired ?
                    this.jsonType.new(value).Cast(clientruntime_1.ClientRuntime.JsonNode) :
                    (0, codegen_csharp_5.Ternery)((0, codegen_csharp_1.IsNotNull)(value), this.jsonType.new(`(${this.baseType})${value}`).Cast(clientruntime_1.ClientRuntime.JsonNode), codegen_csharp_2.dotnet.Null);
            case codemodel_v3_1.KnownMediaType.Xml:
                return this.isRequired ?
                    (0, codegen_csharp_3.toExpression)(`new ${codegen_csharp_2.System.Xml.Linq.XElement}("${serializedName}",${value})`) :
                    (0, codegen_csharp_3.toExpression)(`null != ${value} ? new ${codegen_csharp_2.System.Xml.Linq.XElement}("${serializedName}",${value}) : null`);
            case codemodel_v3_1.KnownMediaType.QueryParameter: {
                const formatSerializedName = serializedName ? `${serializedName}=` : '';
                if (this.isRequired) {
                    return (0, codegen_csharp_3.toExpression)(`"${formatSerializedName}" + ${this.encode}(${value}.ToString())`);
                }
                else {
                    return (0, codegen_csharp_3.toExpression)(`(null == ${value} ? ${codegen_csharp_2.System.String.Empty} : "${formatSerializedName}" + ${this.encode}(${value}.ToString()))`);
                }
                // return toExpression(`if (${value} != null) { queryParameters.Add($"${value}={${value}}"); }`);
            }
            case codemodel_v3_1.KnownMediaType.Cookie:
            case codemodel_v3_1.KnownMediaType.Header:
            case codemodel_v3_1.KnownMediaType.Text:
            case codemodel_v3_1.KnownMediaType.UriParameter:
                return (0, codegen_csharp_3.toExpression)(this.isRequired ?
                    `(${value}.ToString())` :
                    `(null == ${value} ? ${codegen_csharp_2.System.String.Empty} : ${value}.ToString())`);
        }
        return (0, codegen_csharp_3.toExpression)(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`);
    }
    serializeToContainerMember(mediaType, value, container, serializedName, mode) {
        const formatSerializedName = serializedName ? `${serializedName}=` : '';
        switch (mediaType) {
            case codemodel_v3_1.KnownMediaType.Json:
                // container : JsonObject
                return `AddIf( ${this.serializeToNode(mediaType, value, serializedName, mode)}, "${serializedName}" ,${(0, codegen_csharp_3.valueOf)(container)}.Add );`;
            case codemodel_v3_1.KnownMediaType.Xml:
                // container : XElement
                return `AddIf( ${this.serializeToNode(mediaType, value, serializedName, mode)}, ${(0, codegen_csharp_3.valueOf)(container)}.Add );`;
            case codemodel_v3_1.KnownMediaType.Header:
                // container : HttpRequestHeaders
                return this.isRequired ?
                    `${(0, codegen_csharp_3.valueOf)(container)}.Add("${serializedName}",${value}.ToString());` :
                    (0, codegen_csharp_4.If)(`null != ${value}`, `${(0, codegen_csharp_3.valueOf)(container)}.Add("${serializedName}",${value}.ToString());`);
            case codemodel_v3_1.KnownMediaType.QueryParameter:
                // gives a name=value for use inside a c# template string($"foo{someProperty}") as a query parameter
                return this.isRequired ?
                    `${formatSerializedName}{${value}.ToString()}` :
                    `{null == ${value} ? ${codegen_csharp_2.System.String.Empty} : $"${serializedName}={${value}.ToString()}"}`;
            case codemodel_v3_1.KnownMediaType.UriParameter:
                // gives a name=value for use inside a c# template string($"foo{someProperty}") as a query parameter
                return this.isRequired ?
                    `${formatSerializedName}{${value}.ToString()}` :
                    `{null == ${value} ? ${codegen_csharp_2.System.String.Empty}: $"${formatSerializedName}{${value}.ToString()}"}`;
        }
        return (`/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`);
    }
}
exports.NewPrimitive = NewPrimitive;
//# sourceMappingURL=primitive.js.map