"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.applyModelNameModifiersSdk = exports.applyModifiersSdk = void 0;
const extension_base_1 = require("@autorest/extension-base");
const codegen_1 = require("@azure-tools/codegen");
const linq_1 = require("@azure-tools/linq");
const model_state_1 = require("../utils/model-state");
const resolve_conflicts_1 = require("../utils/resolve-conflicts");
let directives = [];
function hasSpecialChars(str) {
    return !/^[a-zA-Z0-9]+$/.test(str);
}
function getFilterError(whereObject, prohibitedFilters, selectionType) {
    let error = '';
    for (const each of (0, linq_1.values)(prohibitedFilters)) {
        if (whereObject[each] !== undefined) {
            error += `Can't filter by ${each} when selecting command. `;
        }
    }
    return error;
}
function getSetError(setObject, prohibitedSetters, selectionType) {
    let error = '';
    for (const each of (0, linq_1.values)(prohibitedSetters)) {
        if (setObject[each] !== undefined) {
            error += `Can't set ${each} when a ${selectionType} is selected. `;
        }
    }
    return error;
}
function isWhereModelDirective(it) {
    const directive = it;
    const where = directive.where;
    const set = directive.set;
    if (where && set && (where['model-name'] || where['property-name'] || directive.select === 'model')) {
        return true;
    }
    return false;
}
async function tweakModel(state) {
    var _a;
    // only look at directives without the `transform` node.
    for (const directive of directives.filter(each => !each.transform)) {
        const getPatternToMatch = (selector) => {
            return selector ? !hasSpecialChars(selector) ? new RegExp(`^${selector}$`, 'gi') : new RegExp(selector, 'gi') : undefined;
        };
        if (isWhereModelDirective(directive)) {
            const selectType = directive.select;
            const modelNameRegex = getPatternToMatch(directive.where['model-name']);
            const propertyNameRegex = getPatternToMatch(directive.where['property-name']);
            const modelNameReplacer = directive.set['model-name'];
            const propertyNameReplacer = directive.set['property-name'];
            // select all models
            let models = [...(_a = state.model.schemas.objects) !== null && _a !== void 0 ? _a : []];
            // let models = values(state.model.schemas).toArray();
            if (modelNameRegex) {
                models = (0, linq_1.values)(models)
                    .where(model => { var _a; return !!`${(_a = model.language.csharp) === null || _a === void 0 ? void 0 : _a.name}`.match(modelNameRegex); })
                    .toArray();
            }
            if (propertyNameRegex && selectType === 'model') {
                models = (0, linq_1.values)(models)
                    .where(model => {
                    var _a;
                    return (0, linq_1.values)((0, resolve_conflicts_1.allVirtualProperties)((_a = model.language.csharp) === null || _a === void 0 ? void 0 : _a.virtualProperties))
                        .any(property => !!`${property.name}`.match(propertyNameRegex));
                })
                    .toArray();
            }
            if (propertyNameRegex && (selectType === undefined || selectType === 'property')) {
                const properties = (0, linq_1.values)(models)
                    .selectMany(model => { var _a; return (0, resolve_conflicts_1.allVirtualProperties)((_a = model.language.csharp) === null || _a === void 0 ? void 0 : _a.virtualProperties); })
                    .where(property => !!`${property.name}`.match(propertyNameRegex))
                    .toArray();
                for (const property of (0, linq_1.values)(properties)) {
                    const prevName = property.name;
                    property.name = propertyNameReplacer ? propertyNameRegex ? property.name.replace(propertyNameRegex, propertyNameReplacer) : propertyNameReplacer : property.name;
                    if (!property.name) {
                        state.message({ Channel: extension_base_1.Channel.Error, Text: `Directive '${directive.where['model-name']}/${directive.where['property-name']}' attempted to change '${prevName}' to '' ` });
                    }
                    if (propertyNameRegex) {
                        state.message({
                            Channel: extension_base_1.Channel.Debug, Text: `[DIRECTIVE] Changed property-name from ${prevName} to ${property.name}.`
                        });
                    }
                }
            }
            else if (models) {
                // comment out below to disable model name change, which will be added in the tweakModelName before the plugin csnamerSdk
                // for (const model of values(models)) {
                //   const prevName = model.language.csharp?.name;
                //   if (model.language.csharp) {
                //     model.language.default.fullname = model.language.csharp.fullname = model.language.default.name = model.language.csharp.name = modelNameReplacer ? modelNameRegex ? model.language.csharp.name.replace(modelNameRegex, modelNameReplacer) : modelNameReplacer : model.language.csharp.name;
                //   }
                //   state.message({
                //     Channel: Channel.Debug, Text: `[DIRECTIVE] Changed model-name from ${prevName} to ${model.language.csharp?.name}.`
                //   });
                // }
            }
        }
    }
    return state.model;
}
async function tweakModelName(state) {
    var _a;
    // only look at directives without the `transform` node.
    for (const directive of directives.filter(each => !each.transform)) {
        const getPatternToMatch = (selector) => {
            return selector ? !hasSpecialChars(selector) ? new RegExp(`^${selector}$`, 'gi') : new RegExp(selector, 'gi') : undefined;
        };
        if (isWhereModelDirective(directive)) {
            const selectType = directive.select;
            const modelNameRegex = getPatternToMatch(directive.where['model-name']);
            const propertyNameRegex = getPatternToMatch(directive.where['property-name']);
            const modelNameReplacer = directive.set['model-name'];
            const propertyNameReplacer = directive.set['property-name'];
            // select all models
            let models = [...(_a = state.model.schemas.objects) !== null && _a !== void 0 ? _a : []];
            // let models = values(state.model.schemas).toArray();
            if (modelNameRegex) {
                models = (0, linq_1.values)(models)
                    .where(model => !!`${model.language.default.name}`.match(modelNameRegex))
                    .toArray();
            }
            if (propertyNameRegex && selectType === 'model') {
                models = (0, linq_1.values)(models)
                    .where(model => (0, linq_1.values)((0, resolve_conflicts_1.allVirtualProperties)(model.language.default.virtualProperties))
                    .any(property => !!`${property.name}`.match(propertyNameRegex)))
                    .toArray();
            }
            if (propertyNameRegex && (selectType === undefined || selectType === 'property')) {
                // skip directive for property
            }
            else if (models) {
                for (const model of (0, linq_1.values)(models)) {
                    const prevName = model.language.default.name;
                    model.language.default.name = modelNameReplacer ? modelNameRegex ? model.language.default.name.replace(modelNameRegex, modelNameReplacer) : modelNameReplacer : model.language.default.name;
                    state.message({
                        Channel: extension_base_1.Channel.Debug, Text: `[DIRECTIVE] Changed model-name from ${prevName} to ${model.language.default.name}.`
                    });
                }
            }
        }
    }
    return state.model;
}
async function applyModifiersSdk(service) {
    // dolauli implement directives
    const allDirectives = await service.getValue('directive');
    directives = (0, linq_1.values)(allDirectives)
        // .select(directive => directive)
        .where(directive => isWhereModelDirective(directive))
        .toArray();
    const state = await new model_state_1.ModelState(service).init();
    const result = await tweakModel(state);
    await service.writeFile({ filename: 'code-model-v4-modifiers-sdk.yaml', content: (0, codegen_1.serialize)(result), sourceMap: undefined, artifactType: 'code-model-sdk' });
}
exports.applyModifiersSdk = applyModifiersSdk;
async function applyModelNameModifiersSdk(service) {
    // dolauli implement directives
    const allDirectives = await service.getValue('directive');
    directives = (0, linq_1.values)(allDirectives)
        // .select(directive => directive)
        .where(directive => isWhereModelDirective(directive))
        .toArray();
    const state = await new model_state_1.ModelState(service).init();
    const result = await tweakModelName(state);
    await service.writeFile({ filename: 'code-model-v4-model-name-modifiers-sdk.yaml', content: (0, codegen_1.serialize)(result), sourceMap: undefined, artifactType: 'code-model-sdk' });
}
exports.applyModelNameModifiersSdk = applyModelNameModifiersSdk;
//# sourceMappingURL=sdk-modifiers.js.map