"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.ResolvedTrait = void 0;
const internal_1 = require("../internal");
/**
     * @internal
     */
class ResolvedTrait {
    constructor(trait, pc, values, wasSet, explicitVerb, metaTraits) {
        // let bodyCode = () =>
        {
            if (pc && pc.sequence && pc.sequence.length) {
                this.parameterValues = new internal_1.ParameterValueSet(trait.ctx, pc, values, wasSet);
            }
            this.trait = trait;
            this.explicitVerb = explicitVerb;
            if (metaTraits !== undefined) {
                this.metaTraits = metaTraits.slice(0);
            }
        }
        // return p.measure(bodyCode);
    }
    get traitName() {
        // let bodyCode = () =>
        {
            return this.trait.declaredPath;
        }
        // return p.measure(bodyCode);
    }
    spew(resOpt, to, indent) {
        // let bodyCode = () =>
        {
            to.spewLine(`${indent}[${this.traitName}]`);
            if (this.parameterValues) {
                this.parameterValues.spew(resOpt, to, `${indent}-`);
            }
        }
        // return p.measure(bodyCode);
    }
    copy() {
        // let bodyCode = () =>
        {
            let pc = undefined;
            let values = undefined;
            let wasSet = undefined;
            let metaTraits = undefined;
            if (this.parameterValues) {
                const copyParamValues = this.parameterValues.copy();
                pc = copyParamValues.pc;
                values = copyParamValues.values;
                wasSet = copyParamValues.wasSet;
            }
            if (this.metaTraits !== undefined) {
                metaTraits = this.metaTraits.slice(0);
            }
            return new ResolvedTrait(this.trait, pc, values, wasSet, this.explicitVerb, metaTraits);
        }
        // return p.measure(bodyCode);
    }
    collectTraitNames(resOpt, into) {
        // let bodyCode = () =>
        {
            // get the name of this trait and all of its base classes
            let t = this.trait;
            while (t) {
                const name = t.getName();
                if (!into.has(name)) {
                    into.add(name);
                }
                const baseRef = t.fetchExtendsTrait();
                t = (baseRef ? baseRef.fetchObjectDefinition(resOpt) : undefined);
            }
        }
        // return p.measure(bodyCode);
    }
    /// Adds a 'meta' trait to a resolved trait object
    /// collection stays null until used to save space
    /// </summary>
    /// <param name="trait"> the trait reference to place in the metaTraits collection</param>
    /// <param name="verb"> a verb trait to use along with the ref. can be null for default verb</param>
    addMetaTrait(trait, verb) {
        if (this.metaTraits === undefined) {
            this.metaTraits = new Array();
        }
        trait.verb = verb;
        this.metaTraits.push(trait);
    }
    /// creates a TraitProfile from a resolved trait
    /// normally these would come from a trait reference or definition, so we need to 
    /// put some things back together to make this look right
    /// <param name="resOpt"></param>
    /// <param name="cache">optional cache object to speed up and make consistent the fetching of profiles for a larger set of objects</param>
    /// <param name="forVerb">optional 'verb' name to use as a filter. I only want profiles applied with 'means' for example</param>
    /// <returns>the profile object, perhaps from the cache</returns>
    fetchTraitProfile(resOpt, cache = undefined, forVerb = undefined) {
        if (cache === undefined) {
            cache = new internal_1.traitProfileCache();
        }
        // start with the profile of the definition
        let definition = internal_1.traitProfile.traitDefToProfile(this.trait, resOpt, false, false, cache);
        let result = new internal_1.traitProfile();
        // encapsulate and promote
        result.references = definition;
        result.traitName = definition.traitName;
        // move over any verb set or metatraits set on this reference
        if (this.explicitVerb !== undefined) {
            result.verb = internal_1.traitProfile.traitRefToProfile(this.explicitVerb, resOpt, true, true, true, cache);
        }
        if (result.verb !== undefined && forVerb !== undefined && result.verb.traitName !== forVerb) {
            // filter out now
            result = undefined;
        }
        else {
            if (this.metaTraits !== undefined) {
                result.metaTraits = internal_1.traitProfile.traitCollectionToProfileList(this.metaTraits, resOpt, result.metaTraits, true, cache);
                result.removeClassifiersFromMeta();
            }
            // if there are arguments set in this resolved trait, list them
            if (this.parameterValues !== undefined && this.parameterValues.length > 0) {
                let argMap = new Map();
                let l = this.parameterValues.length;
                for (let i = 0; i < l; i++) {
                    let p = this.parameterValues.fetchParameterAtIndex(i);
                    let v = this.parameterValues.fetchValue(i);
                    let name = p.name;
                    if (name === undefined) {
                        name = i.toString();
                    }
                    var value = internal_1.traitProfile.fetchProfileArgumentFromTraitArgument(v, resOpt);
                    if (value !== undefined) {
                        argMap.set(name, value);
                    }
                }
                if (argMap.size > 0) {
                    result.argumentValues = argMap;
                }
            }
        }
        return result;
    }
}
exports.ResolvedTrait = ResolvedTrait;
//# sourceMappingURL=ResolvedTrait.js.map