"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.Project = exports.PSSchemaResolver = exports.NewPSSwitch = void 0;
const linq_1 = require("@azure-tools/linq");
const exports_1 = require("../llcsharp/exports");
const state_1 = require("./state");
const codegen_csharp_1 = require("@azure-tools/codegen-csharp");
const model_extensions_1 = require("../models/model-extensions");
const powershell_comment_1 = require("../utils/powershell-comment");
const module_namespace_1 = require("../module/module-namespace");
const namespace_1 = require("../cmdlets/namespace");
const codegen_1 = require("@azure-tools/codegen");
const codemodel_1 = require("@autorest/codemodel");
class NewPSSwitch extends exports_1.Boolean {
    get declaration() {
        return `global::System.Management.Automation.SwitchParameter${this.isRequired ? '' : '?'}`;
    }
}
exports.NewPSSwitch = NewPSSwitch;
class PSSchemaResolver extends exports_1.SchemaDefinitionResolver {
    constructor() {
        super(...arguments);
        this.inResolve = false;
    }
    resolveTypeDeclaration(schema, required, state, isFixedArray) {
        const before = this.inResolve;
        try {
            if (!this.inResolve) {
                this.inResolve = true;
                if (schema &&
                    (schema.type === codemodel_1.SchemaType.Boolean ||
                        (schema.type === codemodel_1.SchemaType.Constant &&
                            schema.valueType.type === codemodel_1.SchemaType.Boolean) ||
                        (schema.type === codemodel_1.SchemaType.Choice &&
                            schema.choiceType.type === codemodel_1.SchemaType.Boolean))) {
                    return new NewPSSwitch(schema, required);
                }
            }
            return super.resolveTypeDeclaration(schema, required, state, isFixedArray);
        }
        finally {
            this.inResolve = before;
        }
    }
}
exports.PSSchemaResolver = PSSchemaResolver;
class Project extends codegen_csharp_1.Project {
    get model() {
        return this.state.model;
    }
    constructor(service, objectInitializer) {
        super();
        this.service = service;
        this.apply(objectInitializer);
    }
    async init(state) {
        var _a;
        await super.init();
        this.state = await new state_1.State(this.service).init(this);
        if (state) {
            this.state.model = state.model;
        }
        this.schemaDefinitionResolver = new PSSchemaResolver(this.state.project.fixedArray);
        this.projectNamespace = ((_a = this.state.model.language.csharp) === null || _a === void 0 ? void 0 : _a.namespace) || '';
        this.overrides = {
            'Carbon.Json.Converters': `${this.projectNamespace}.Runtime.Json`,
            'Carbon.Internal.Extensions': `${this.projectNamespace}.Runtime.Json`,
            'Carbon.Internal': `${this.projectNamespace}.Runtime.Json`,
            'Carbon.Data': `${this.projectNamespace}.Runtime.Json`,
            'using Data;': '',
            'using Parser;': '',
            'using Converters;': '',
            'using Internal.Extensions;': '',
            'Carbon.Json.Parser': `${this.projectNamespace}.Runtime.Json`,
            'Carbon.Json': `${this.projectNamespace}.Runtime.Json`,
            'Microsoft.Rest.ClientRuntime': `${this.projectNamespace}.Runtime`,
            'Microsoft.Message.ClientRuntime': `${this.projectNamespace}.Runtime`,
            'Microsoft.generated.runtime.Properties': `${this.projectNamespace}.generated.runtime.Properties`,
            'Microsoft.Rest': `${this.projectNamespace}`,
        };
        // Values
        this.moduleVersion = await this.state.getValue('module-version');
        // skip-for-time-being
        //this.profiles = this.model.info.extensions['x-ms-metadata'].profiles || [];
        this.profiles = [];
        this.accountsVersionMinimum = '2.7.5';
        this.helpLinkPrefix = await this.state.getValue('help-link-prefix');
        this.metadata = await this.state.getValue('metadata');
        this.preprocessMetadata();
        this.license = await this.state.getValue('header-text', '');
        const pwshLicenseHeader = await this.state.getValue('pwsh-license-header', '');
        // if pwsh license header is not set, use the license set by license-header
        this.pwshCommentHeader = (0, codegen_1.comment)(pwshLicenseHeader
            ? (0, powershell_comment_1.pwshHeaderText)(pwshLicenseHeader, await this.service.getValue('header-definitions'))
            : this.license, '#');
        this.pwshCommentHeaderForCsharp = this.pwshCommentHeader.replace(/"/g, '""');
        this.csharpCommentHeader = (0, codegen_1.comment)(pwshLicenseHeader
            ? (0, powershell_comment_1.pwshHeaderText)(pwshLicenseHeader, await this.service.getValue('header-definitions'))
            : this.license, '//');
        this.csharpCommentHeaderForCsharp = this.csharpCommentHeader.replace(/"/g, '""');
        // modelcmdlets are models that we will create cmdlets for.
        this.modelCmdlets = [];
        let directives = [];
        const allDirectives = await this.state.service.getValue('directive');
        directives = (0, linq_1.values)(allDirectives).toArray();
        for (const directive of directives.filter((each) => each['model-cmdlet'])) {
            this.modelCmdlets = this.modelCmdlets.concat((0, linq_1.values)(directive['model-cmdlet']).toArray());
        }
        this.modelCmdletsInPS = this.modelCmdlets.map(each => `@{modelName="${each['model-name']}"; cmdletName="${each['cmdlet-name'] || ''}"}`).join(', ') || '';
        // input handlers
        this.inputHandlers = await this.state.getValue('input-handlers', []);
        // Flags
        this.azure = this.model.language.default.isAzure;
        this.addToString = await this.state.getValue('nested-object-to-string', this.azure ? true : false);
        // Names
        this.prefix = this.model.language.default.prefix;
        this.serviceName = this.model.language.default.serviceName;
        this.subjectPrefix = this.model.language.default.subjectPrefix;
        this.moduleName = await this.state.getValue('module-name');
        this.title = await this.state.getValue('title');
        this.rootModuleName = await this.state.getValue('root-module-name', '');
        this.dllName = await this.state.getValue('dll-name');
        // Azure PowerShell data plane configuration
        if (this.azure) {
            this.endpointResourceIdKeyName = await this.state.getValue('endpoint-resource-id-key-name', '');
            this.endpointSuffixKeyName = await this.state.getValue('endpoint-suffix-key-name', '');
        }
        // Folders
        this.baseFolder = await this.state.getValue('current-folder');
        this.moduleFolder = await this.state.getValue('module-folder');
        this.cmdletFolder = await this.state.getValue('cmdlet-folder');
        this.modelCmdletFolder = await this.state.getValue('model-cmdlet-folder');
        this.customFolder = await this.state.getValue('custom-cmdlet-folder');
        this.utilsFolder = await this.state.getValue('utils-cmdlet-folder');
        this.internalFolder = await this.state.getValue('internal-cmdlet-folder');
        this.testFolder = await this.state.getValue('test-folder');
        this.runtimeFolder = await this.state.getValue('runtime-folder');
        this.apiFolder = await this.state.getValue('api-folder');
        this.binFolder = await this.state.getValue('bin-folder');
        this.objFolder = await this.state.getValue('obj-folder');
        this.exportsFolder = await this.state.getValue('exports-folder');
        this.docsFolder = await this.state.getValue('docs-folder');
        this.dependencyModuleFolder = await this.state.getValue('dependency-module-folder');
        this.examplesFolder = await this.state.getValue('examples-folder');
        this.resourcesFolder = await this.state.getValue('resources-folder');
        this.uxFolder = await this.state.getValue('ux-folder');
        // configuration for whether to use fixed array in generated code of model, default is false
        this.fixedArray = await this.state.getValue('fixed-array', false);
        // File paths
        this.csproj = await this.state.getValue('csproj');
        this.dll = await this.state.getValue('dll');
        this.psd1 = await this.state.getValue('psd1');
        this.psm1 = await this.state.getValue('psm1');
        this.psm1Custom = await this.state.getValue('psm1-custom');
        this.psm1Internal = await this.state.getValue('psm1-internal');
        this.formatPs1xml = await this.state.getValue('format-ps1xml');
        this.autoSwitchView = await this.state.getValue('auto-switch-view', true);
        this.nuspec = await this.state.getValue('nuspec');
        this.gitIgnore = `${this.baseFolder}/.gitignore`;
        this.gitAttributes = `${this.baseFolder}/.gitattributes`;
        this.readme = `${this.baseFolder}/README.md`;
        this.afterBuildTasksPath = await this.state.getValue('after-build-tasks-path', '');
        const afterBuildTasksArgsDictionary = await this.state.getValue('after-build-tasks-args', {});
        this.afterBuildTasksArgs = JSON.stringify(afterBuildTasksArgsDictionary);
        this.assemblyInfoPath = await this.state.getValue('assemblyInfo-path', '');
        this.assemblyCompany = await this.state.getValue('assembly-company', '');
        this.assemblyProduct = await this.state.getValue('assembly-product', '');
        this.assemblyCopyright = await this.state.getValue('assembly-copyright', '');
        // excluded properties in table view
        const excludedList = ((0, linq_1.values)(await this.state.getValue('exclude-tableview-properties', [])).toArray());
        this.propertiesExcludedForTableview = excludedList
            ? excludedList.join(',')
            : '';
        // add project namespace
        this.serviceNamespace = new module_namespace_1.ModuleNamespace(this.state);
        this.serviceNamespace.header = this.license;
        this.addNamespace(this.serviceNamespace);
        this.modelsExtensions = new model_extensions_1.ModelExtensionsNamespace(this.serviceNamespace, this.state.model.schemas, this.state.path('components', 'schemas'));
        this.modelsExtensions.header = this.license;
        this.addNamespace(this.modelsExtensions);
        // add cmdlet namespace
        this.cmdlets = await new namespace_1.CmdletNamespace(this.serviceNamespace, this.state).init();
        this.cmdlets.header = this.license;
        this.addNamespace(this.cmdlets);
        // abort now if we have any errors.
        this.state.checkpoint();
        return this;
    }
    /**
     * Preprocess some list properties in metadata to string properties,
     * so they can be easily used in csharp templates.
     */
    preprocessMetadata() {
        var _a;
        if (this.metadata) {
            this.metadata = {
                ...this.metadata,
                requiredModulesAsString: this.metadata.requiredModules
                    ? (_a = this.metadata.requiredModules
                        .map((m) => `@{ModuleName = '${m.name}'; ModuleVersion = '${m.version}'}`)) === null || _a === void 0 ? void 0 : _a.join(', ')
                    : 'undefined',
                requiredAssembliesAsString: this.convertToPsListAsString(this.metadata.requiredAssemblies),
                nestedModulesAsString: this.convertToPsListAsString(this.metadata.nestedModules),
                formatsToProcessAsString: this.convertToPsListAsString(this.metadata.formatsToProcess),
                typesToProcessAsString: this.convertToPsListAsString(this.metadata.typesToProcess),
                scriptsToProcessAsString: this.convertToPsListAsString(this.metadata.scriptsToProcess),
                functionsToExportAsString: this.convertToPsListAsString(this.metadata.functionsToExport),
                cmdletsToExportAsString: this.convertToPsListAsString(this.metadata.cmdletsToExport),
                aliasesToExportAsString: this.convertToPsListAsString(this.metadata.aliasesToExport),
            };
        }
    }
    convertToPsListAsString(items) {
        return items ? items.map((i) => `'${i}'`).join(', ') : 'undefined';
    }
}
exports.Project = Project;
//# sourceMappingURL=project.js.map