"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DictionaryImplementation = void 0;
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
const codegen_csharp_1 = require("@azure-tools/codegen-csharp");
const clientruntime_1 = require("../clientruntime");
const codemodel_v3_1 = require("@azure-tools/codemodel-v3");
const codemodel_1 = require("@autorest/codemodel");
class DictionaryImplementation extends codegen_csharp_1.Class {
    get state() { return this.modelClass.state; }
    get schema() { return this.modelClass.schema; }
    constructor(modelClass, objectInitializer) {
        super(modelClass.namespace, modelClass.name);
        this.modelClass = modelClass;
        this.ownsDictionary = false;
        this.apply(objectInitializer);
    }
    init(valueType, accessViaMember) {
        var _a, _b;
        if (valueType && accessViaMember) {
            this.valueType = valueType;
            this.implementIDictionary(this, '', codegen_csharp_1.System.String, valueType, accessViaMember);
        }
        else {
            const dictSchema = this.schema.type === codemodel_1.SchemaType.Dictionary ? this.schema : (_b = (_a = this.schema.parents) === null || _a === void 0 ? void 0 : _a.immediate) === null || _b === void 0 ? void 0 : _b.find((s) => s.type === codemodel_1.SchemaType.Dictionary);
            if (dictSchema) {
                this.ownsDictionary = true;
                this.valueType = dictSchema.elementType.type === codemodel_1.SchemaType.Any ? codegen_csharp_1.System.Object : this.state.project.modelsNamespace.NewResolveTypeDeclaration(dictSchema.elementType, true, this.state);
                this.modelClass.modelInterface.interfaces.push(this.implementIDictionary(this, 'additionalProperties', codegen_csharp_1.System.String, this.valueType));
            }
        }
        return this;
    }
    addSerialization() {
        if (this.modelClass.jsonSerializer) {
            // add serializer methods.
            // this.modelClass.jsonSerializer
        }
    }
    implementIDictionary(targetClass, name, keyType, valueType, accessViaMember) {
        var _a;
        const containerInterfaceType = { declaration: `${clientruntime_1.ClientRuntime}.IAssociativeArray<${valueType.declaration}>`, allProperties: [] };
        const dictionaryInterfaceType = codegen_csharp_1.System.Collections.Generic.IDictionary(keyType, valueType);
        const itemType = codegen_csharp_1.System.Collections.Generic.KeyValuePair(keyType, valueType);
        // add the interface to the list of interfaces for the class
        targetClass.interfaces.push(containerInterfaceType);
        // the backing field
        const dictionaryType = codegen_csharp_1.System.Collections.Generic.Dictionary(keyType, valueType);
        accessViaMember = accessViaMember || targetClass.add(new codegen_csharp_1.Field(`__${name}`, dictionaryType, { access: codegen_csharp_1.Access.Protected, initialValue: dictionaryType.new() }));
        const indexer = targetClass.add(new codegen_csharp_1.Indexer(keyType, valueType, { get: (0, codegen_csharp_1.toExpression)(`${accessViaMember}[index]`), set: (0, codegen_csharp_1.toExpression)(`${accessViaMember}[index] = value`) }));
        // the parameters used in methods.
        const pKey = new codegen_csharp_1.Parameter('key', keyType);
        const pValue = new codegen_csharp_1.Parameter('value', valueType);
        const pOutValue = new codegen_csharp_1.Parameter('value', valueType, { modifier: codegen_csharp_1.ParameterModifier.Out });
        if (this.state.project.exportPropertiesForDict) {
            targetClass.add(new codegen_csharp_1.Property(`${containerInterfaceType.declaration}.Keys`, codegen_csharp_1.System.Collections.Generic.IEnumerable(keyType), { get: (0, codegen_csharp_1.toExpression)(`${accessViaMember}.Keys`), getAccess: codegen_csharp_1.Access.Explicit }));
            targetClass.add(new codegen_csharp_1.Property(`${containerInterfaceType.declaration}.Values`, codegen_csharp_1.System.Collections.Generic.IEnumerable(valueType), { get: (0, codegen_csharp_1.toExpression)(`${accessViaMember}.Values`), getAccess: codegen_csharp_1.Access.Explicit }));
            targetClass.add(new codegen_csharp_1.Property(`${containerInterfaceType.declaration}.Count`, codegen_csharp_1.dotnet.Int, { get: (0, codegen_csharp_1.toExpression)(`${accessViaMember}.Count`), getAccess: codegen_csharp_1.Access.Explicit }));
        }
        if (name) {
            targetClass.add(new codegen_csharp_1.ImplicitCastOperator(dictionaryType, targetClass, `source.${accessViaMember}`));
            targetClass.add(new codegen_csharp_1.Property(`${containerInterfaceType.declaration}.AdditionalProperties`, dictionaryInterfaceType, { get: (0, codegen_csharp_1.toExpression)(`${accessViaMember}`), getAccess: codegen_csharp_1.Access.Explicit }));
        }
        else {
            targetClass.add(new codegen_csharp_1.Property(`${containerInterfaceType.declaration}.AdditionalProperties`, dictionaryInterfaceType, { get: (0, codegen_csharp_1.toExpression)(`${accessViaMember}.AdditionalProperties`), getAccess: codegen_csharp_1.Access.Explicit }));
        }
        targetClass.add(new codegen_csharp_1.Method('Add', codegen_csharp_1.dotnet.Void, { parameters: [pKey, pValue], body: (0, codegen_csharp_1.toExpression)(`${accessViaMember}.Add( ${pKey}, ${pValue})`), access: codegen_csharp_1.Access.Public }));
        targetClass.add(new codegen_csharp_1.Method('Clear', codegen_csharp_1.dotnet.Void, { body: (0, codegen_csharp_1.toExpression)(`${accessViaMember}.Clear()`), access: codegen_csharp_1.Access.Public }));
        targetClass.add(new codegen_csharp_1.Method('ContainsKey', codegen_csharp_1.dotnet.Bool, { parameters: [pKey], body: (0, codegen_csharp_1.toExpression)(`${accessViaMember}.ContainsKey( ${pKey})`), access: codegen_csharp_1.Access.Public }));
        targetClass.add(new codegen_csharp_1.Method('Remove', codegen_csharp_1.dotnet.Bool, { parameters: [pKey], body: (0, codegen_csharp_1.toExpression)(`${accessViaMember}.Remove( ${pKey})`), access: codegen_csharp_1.Access.Public }));
        targetClass.add(new codegen_csharp_1.Method('TryGetValue', codegen_csharp_1.dotnet.Bool, { parameters: [pKey, pOutValue], body: (0, codegen_csharp_1.toExpression)(`${accessViaMember}.TryGetValue( ${pKey}, out ${pOutValue})`), access: codegen_csharp_1.Access.Public }));
        const all = (0, codemodel_v3_1.getAllVirtualProperties)((_a = this.schema.language.csharp) === null || _a === void 0 ? void 0 : _a.virtualProperties);
        const exclusions = all.map(each => `"${each.name}"`).join(',');
        // add a CopyFrom that takes an IDictionary or PSObject and copies the values into this dictionary
        for (const pDictType of [codegen_csharp_1.System.Collections.IDictionary, { declaration: 'global::System.Management.Automation.PSObject' }]) {
            const pDict = new codegen_csharp_1.Parameter('source', pDictType);
            targetClass.add(new codegen_csharp_1.Method('CopyFrom', codegen_csharp_1.dotnet.Void, {
                parameters: [pDict], body: function* () {
                    yield (0, codegen_csharp_1.If)(pDict.IsNotNull, function* () {
                        yield (0, codegen_csharp_1.ForEach)('property', ` Microsoft.Rest.ClientRuntime.PowerShell.TypeConverterExtensions.GetFilteredProperties(${pDict.value}, ${codegen_csharp_1.System.Collections.Generic.HashSet(codegen_csharp_1.System.String).new()} { ${exclusions} } )`, function* () {
                            yield (0, codegen_csharp_1.If)((0, codegen_csharp_1.And)('null != property.Key', 'null != property.Value'), function* () {
                                yield `this.${accessViaMember}.Add(property.Key.ToString(), global::System.Management.Automation.LanguagePrimitives.ConvertTo<${valueType.declaration}>( property.Value));`;
                            });
                        });
                    });
                }
            }));
        }
        // return dictionaryInterfaceType;
        return containerInterfaceType;
    }
    get fileName() {
        return `${super.fileName}.dictionary`;
    }
}
exports.DictionaryImplementation = DictionaryImplementation;
//# sourceMappingURL=model-class-dictionary.js.map