"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.getCommandName = exports.singularize = void 0;
const codegen_1 = require("@azure-tools/codegen");
const extension_base_1 = require("@autorest/extension-base");
const linq_1 = require("@azure-tools/linq");
function getPluralizationService() {
    const result = new codegen_1.EnglishPluralizationService();
    result.addWord('Database', 'Databases');
    result.addWord('database', 'databases');
    result.addWord('Premise', 'Premises');
    result.addWord('premise', 'premises');
    return result;
}
function singularize(word) {
    return getPluralizationService().singularize(word);
}
exports.singularize = singularize;
function getSingularizedValue(name) {
    return (0, codegen_1.pascalCase)([singularize(name)]);
}
const cmdVerbMapGetVerb = {
    'Add': 'Common',
    'Clear': 'Common',
    'Close': 'Common',
    'Copy': 'Common',
    'Enter': 'Common',
    'Exit': 'Common',
    'Find': 'Common',
    'Format': 'Common',
    'Get': 'Common',
    'Hide': 'Common',
    'Join': 'Common',
    'Lock': 'Common',
    'Move': 'Common',
    'New': 'Common',
    'Open': 'Common',
    'Optimize': 'Common',
    'Pop': 'Common',
    'Push': 'Common',
    'Redo': 'Common',
    'Remove': 'Common',
    'Rename': 'Common',
    'Reset': 'Common',
    'Resize': 'Common',
    'Search': 'Common',
    'Select': 'Common',
    'Set': 'Common',
    'Show': 'Common',
    'Skip': 'Common',
    'Split': 'Common',
    'Step': 'Common',
    'Switch': 'Common',
    'Undo': 'Common',
    'Unlock': 'Common',
    'Watch': 'Common',
    'Backup': 'Data',
    'Checkpoint': 'Data',
    'Compare': 'Data',
    'Compress': 'Data',
    'Convert': 'Data',
    'ConvertFrom': 'Data',
    'ConvertTo': 'Data',
    'Dismount': 'Data',
    'Edit': 'Data',
    'Expand': 'Data',
    'Export': 'Data',
    'Group': 'Data',
    'Import': 'Data',
    'Initialize': 'Data',
    'Limit': 'Data',
    'Merge': 'Data',
    'Mount': 'Data',
    'Out': 'Data',
    'Publish': 'Data',
    'Restore': 'Data',
    'Save': 'Data',
    'Sync': 'Data',
    'Unpublish': 'Data',
    'Update': 'Data',
    'Approve': 'Lifecycle',
    'Assert': 'Lifecycle',
    'Complete': 'Lifecycle',
    'Confirm': 'Lifecycle',
    'Deny': 'Lifecycle',
    'Disable': 'Lifecycle',
    'Enable': 'Lifecycle',
    'Install': 'Lifecycle',
    'Invoke': 'Lifecycle',
    'Register': 'Lifecycle',
    'Request': 'Lifecycle',
    'Restart': 'Lifecycle',
    'Resume': 'Lifecycle',
    'Start': 'Lifecycle',
    'Stop': 'Lifecycle',
    'Submit': 'Lifecycle',
    'Suspend': 'Lifecycle',
    'Uninstall': 'Lifecycle',
    'Unregister': 'Lifecycle',
    'Wait': 'Lifecycle',
    'Debug': 'Diagnostic',
    'Measure': 'Diagnostic',
    'Ping': 'Diagnostic',
    'Repair': 'Diagnostic',
    'Resolve': 'Diagnostic',
    'Test': 'Diagnostic',
    'Trace': 'Diagnostic',
    'Connect': 'Communications',
    'Disconnect': 'Communications',
    'Read': 'Communications',
    'Receive': 'Communications',
    'Send': 'Communications',
    'Write': 'Communications',
    'Block': 'Security',
    'Grant': 'Security',
    'Protect': 'Security',
    'Revoke': 'Security',
    'Unblock': 'Security',
    'Unprotect': 'Security',
    'Use': 'Other',
};
const cmdVerbMapCustom = {
    'Access': 'Get',
    'List': 'Get',
    'Cat': 'Get',
    'Type': 'Get',
    'Dir': 'Get',
    'Obtain': 'Get',
    'Dump': 'Get',
    'Acquire': 'Get',
    'Examine': 'Get',
    'Suggest': 'Get',
    'Retrieve': 'Get',
    'Create': 'New',
    'Generate': 'New',
    'Allocate': 'New',
    'Provision': 'New',
    'Make': 'New',
    'Regenerate': 'New',
    'Replace': 'Update',
    'Failover': 'Set',
    'Assign': 'Set',
    'Configure': 'Set',
    'Activate': 'Initialize',
    'Build': 'Build',
    'Compile': 'Build',
    'Deploy': 'Deploy',
    'Apply': 'Add',
    'Append': 'Add',
    'Attach': 'Add',
    'Concatenate': 'Add',
    'Insert': 'Add',
    'Delete': 'Remove',
    'Cut': 'Remove',
    'Dispose': 'Remove',
    'Discard': 'Remove',
    'Generalize': 'Reset',
    'Patch': 'Update',
    'Refresh': 'Update',
    'Reprocess': 'Update',
    'Upgrade': 'Update',
    'Reimage': 'Update',
    'Retarget': 'Update',
    'Validate': 'Test',
    'Check': 'Test',
    'Verify': 'Test',
    'Analyze': 'Test',
    'Is': 'Test',
    'Evaluate': 'Test',
    'Power': 'Start',
    'PowerOn': 'Start',
    'Run': 'Start',
    'Trigger': 'Start',
    'Pause': 'Suspend',
    'Cancel': 'Stop',
    'PowerOff': 'Stop',
    'End': 'Stop',
    'Shutdown': 'Stop',
    'Reboot': 'Restart',
    'ForceReboot': 'Restart',
    'Finish': 'Complete',
    'Wipe': 'Clear',
    'Purge': 'Clear',
    'Flush': 'Clear',
    'Erase': 'Clear',
    'Unmark': 'Clear',
    'Unset': 'Clear',
    'Nullify': 'Clear',
    'Recover': 'Restore',
    'Undelete': 'Restore',
    'Synchronize': 'Sync',
    'Synch': 'Sync',
    'Load': 'Import',
    'Capture': 'Export',
    'Migrate': 'Move',
    'Transfer': 'Move',
    'Name': 'Move',
    'Reassociate': 'Move',
    'Change': 'Rename',
    'Swap': 'Switch',
    'Execute': 'Invoke',
    'Perform': 'Invoke',
    'Discover': 'Find',
    'Locate': 'Find',
    'Release': 'Publish',
    'Resubmit': 'Submit',
    'Duplicate': 'Copy',
    'Clone': 'Copy',
    'Replicate': 'Copy',
    'Into': 'Enter',
    'Combine': 'Join',
    'Unite': 'Join',
    'Associate': 'Join',
    'Restrict': 'Lock',
    'Secure': 'Lock',
    'Unrestrict': 'Unlock',
    'Unsecure': 'Unlock',
    'Display': 'Show',
    'Produce': 'Show',
    'Bypass': 'Skip',
    'Jump': 'Skip',
    'Separate': 'Split',
    'Notify': 'Send',
    'Authorize': 'Grant'
};
const cmdVerbMap = { ...cmdVerbMapGetVerb, ...cmdVerbMapCustom };
function mapVerb(verb) {
    verb = verb.toLowerCase();
    const keyHits = Object.keys(cmdVerbMap).filter(key => key.toLowerCase() === verb);
    if ((0, linq_1.length)(keyHits) === 0) {
        return [];
    }
    let value = cmdVerbMap[keyHits[0]];
    if (!Array.isArray(value)) {
        value = [value];
    }
    return value;
}
function existsVerb(verb) {
    return mapVerb(verb).length > 0;
}
function getCommandName(operationId, onMessage) {
    const opIdValues = operationId.split('_', 2);
    // OperationId can be specified without '_' (Underscore), Verb will retrieved by the below logic for non-approved verbs.
    let cmdNoun = (0, linq_1.length)(opIdValues) === 2 ? getSingularizedValue(opIdValues[0]) : '';
    let cmdVerb = (0, linq_1.length)(opIdValues) === 2 ? opIdValues[1] : getSingularizedValue(operationId);
    let cmdVerbs = [cmdVerb];
    const variant = operationId;
    if (!Object
        .keys(cmdVerbMapGetVerb)
        .map(v => v.toLowerCase())
        .includes(cmdVerb.toLowerCase())) {
        const unapprovedVerb = cmdVerb;
        onMessage({ Channel: extension_base_1.Channel.Information, Text: `Operation '${operationId}': Verb '${unapprovedVerb}' not an approved verb.` });
        if (Object
            .keys(cmdVerbMapCustom)
            .map(v => v.toLowerCase())
            .includes(cmdVerb.toLowerCase())) {
            // This condition happens when there aren't any suffixes
            cmdVerbs = mapVerb(cmdVerb);
            for (const v of cmdVerbs) {
                onMessage({ Channel: extension_base_1.Channel.Information, Text: `Operation '${operationId}': Using verb '${v}' in place of '${unapprovedVerb}'.` });
            }
        }
        else {
            // This condition happens in cases like: CreateSuffix, CreateOrUpdateSuffix
            let longestVerbMatch = null;
            let currentVerbCandidate = '';
            let firstWord = '';
            let firstWordStarted = false;
            let buildFirstWord = false;
            let firstWordEnd = -1;
            let verbMatchEnd = -1;
            for (let i = 0; i < (0, linq_1.length)(unapprovedVerb); ++i) {
                // Add the start condition of the first word so that the end condition is easier
                if (!firstWordStarted) {
                    firstWordStarted = true;
                    buildFirstWord = true;
                }
                else if (buildFirstWord && (unapprovedVerb.charCodeAt(i) >= 65) && (unapprovedVerb.charCodeAt(i) <= 90)) {
                    // Stop building the first word when we encounter another capital letter
                    buildFirstWord = false;
                    firstWordEnd = i;
                }
                if (buildFirstWord) {
                    firstWord += unapprovedVerb.charAt(i);
                }
                currentVerbCandidate += unapprovedVerb.charAt(i);
                if (existsVerb(currentVerbCandidate)) {
                    // The latest verb match is also the longest verb match
                    longestVerbMatch = currentVerbCandidate;
                    verbMatchEnd = i + 1;
                }
            }
            const beginningOfSuffix = longestVerbMatch ? verbMatchEnd : firstWordEnd;
            cmdVerb = longestVerbMatch ? longestVerbMatch : firstWord;
            if (Object
                .keys(cmdVerbMapCustom)
                .map(v => v.toLowerCase())
                .includes(cmdVerb.toLowerCase())) {
                cmdVerbs = mapVerb(cmdVerb);
            }
            else {
                cmdVerbs = [cmdVerb];
            }
            if (-1 !== beginningOfSuffix) {
                // This is still empty when a verb match is found that is the entire string, but it might not be worth checking for that case and skipping the below operation
                const cmdNounSuffix = unapprovedVerb.substring(beginningOfSuffix);
                // Add command noun suffix only when the current noun doesn't contain it or vice-versa.
                if (!cmdNoun) {
                    cmdNoun = (0, codegen_1.pascalCase)([cmdNounSuffix]);
                }
                else if (!cmdNounSuffix.toLowerCase().startsWith('by')) {
                    if (!cmdNoun.toLowerCase().includes(cmdNounSuffix.toLowerCase()) &&
                        !cmdNounSuffix.toLowerCase().includes(cmdNoun.toLowerCase())) {
                        cmdNoun += (0, codegen_1.pascalCase)([cmdNounSuffix]);
                    }
                    else if (cmdNounSuffix.toLowerCase().includes(cmdNoun.toLowerCase())) {
                        cmdNoun = cmdNounSuffix;
                    }
                }
            }
        }
    }
    // Singularize command noun
    if (cmdNoun) {
        cmdNoun = getSingularizedValue(cmdNoun);
    }
    return cmdVerbs.map(v => {
        let verb = (0, codegen_1.pascalCase)([v]);
        if (!cmdNoun) {
            verb = getSingularizedValue(verb);
        }
        onMessage({ Channel: extension_base_1.Channel.Debug, Text: `Operation '${operationId}': Using noun '${cmdNoun}' and verb '${verb}'.` });
        return { noun: cmdNoun, verb, variant };
    });
}
exports.getCommandName = getCommandName;
//# sourceMappingURL=name-inferrer.js.map