"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.CdmTypeAttributeDefinition = void 0;
const internal_1 = require("../internal");
class CdmTypeAttributeDefinition extends internal_1.CdmAttribute {
    constructor(ctx, name) {
        super(ctx, name);
        this.TAG = CdmTypeAttributeDefinition.name;
        // let bodyCode = () =>
        {
            this.objectType = internal_1.cdmObjectType.typeAttributeDef;
            this.traitToPropertyMap = new internal_1.traitToPropertyMap(this);
            this.attributeCount = 1;
        }
        // return p.measure(bodyCode);
    }
    static get objectType() {
        return internal_1.cdmObjectType.typeAttributeDef;
    }
    get isReadOnly() {
        return this.traitToPropertyMap.fetchPropertyValue('isReadOnly');
    }
    set isReadOnly(val) {
        this.traitToPropertyMap.updatePropertyValue('isReadOnly', val);
    }
    get isNullable() {
        return this.traitToPropertyMap.fetchPropertyValue('isNullable');
    }
    set isNullable(val) {
        this.traitToPropertyMap.updatePropertyValue('isNullable', val);
    }
    get sourceName() {
        return this.traitToPropertyMap.fetchPropertyValue('sourceName');
    }
    set sourceName(val) {
        this.traitToPropertyMap.updatePropertyValue('sourceName', val);
    }
    get description() {
        return this.traitToPropertyMap.fetchPropertyValue('description');
    }
    set description(val) {
        this.traitToPropertyMap.updatePropertyValue('description', val);
    }
    get displayName() {
        return this.traitToPropertyMap.fetchPropertyValue('displayName');
    }
    set displayName(val) {
        this.traitToPropertyMap.updatePropertyValue('displayName', val);
    }
    get sourceOrdering() {
        return this.traitToPropertyMap.fetchPropertyValue('sourceOrdering');
    }
    set sourceOrdering(val) {
        this.traitToPropertyMap.updatePropertyValue('sourceOrdering', val);
    }
    get valueConstrainedToList() {
        return this.traitToPropertyMap.fetchPropertyValue('valueConstrainedToList');
    }
    set valueConstrainedToList(val) {
        this.traitToPropertyMap.updatePropertyValue('valueConstrainedToList', val);
    }
    get isPrimaryKey() {
        return this.traitToPropertyMap.fetchPropertyValue('isPrimaryKey');
    }
    get maximumLength() {
        return this.traitToPropertyMap.fetchPropertyValue('maximumLength');
    }
    set maximumLength(val) {
        this.traitToPropertyMap.updatePropertyValue('maximumLength', val);
    }
    get maximumValue() {
        return this.traitToPropertyMap.fetchPropertyValue('maximumValue');
    }
    set maximumValue(val) {
        this.traitToPropertyMap.updatePropertyValue('maximumValue', val);
    }
    get minimumValue() {
        return this.traitToPropertyMap.fetchPropertyValue('minimumValue');
    }
    set minimumValue(val) {
        this.traitToPropertyMap.updatePropertyValue('minimumValue', val);
    }
    get dataFormat() {
        return this.traitToPropertyMap.fetchPropertyValue('dataFormat');
    }
    set dataFormat(val) {
        this.traitToPropertyMap.updatePropertyValue('dataFormat', val);
    }
    get defaultValue() {
        return this.traitToPropertyMap.fetchPropertyValue('defaultValue');
    }
    set defaultValue(val) {
        this.traitToPropertyMap.updatePropertyValue('defaultValue', val);
    }
    get projection() {
        return this._projection;
    }
    set projection(value) {
        if (value) {
            value.owner = this;
        }
        this._projection = value;
    }
    /**
     * @internal
     */
    getProperty(propertyName) {
        return this.traitToPropertyMap.fetchPropertyValue(propertyName, true);
    }
    getObjectType() {
        // let bodyCode = () =>
        {
            return internal_1.cdmObjectType.typeAttributeDef;
        }
        // return p.measure(bodyCode);
    }
    copy(resOpt, host) {
        // let bodyCode = () =>
        {
            if (!resOpt) {
                resOpt = new internal_1.resolveOptions(this, this.ctx.corpus.defaultResolutionDirectives);
            }
            let copy;
            if (!host) {
                copy = new CdmTypeAttributeDefinition(this.ctx, this.name);
            }
            else {
                copy = host;
                copy.name = this.getName();
            }
            copy.dataType = this.dataType ? this.dataType.copy(resOpt) : undefined;
            copy.attributeContext = this.attributeContext ? this.attributeContext.copy(resOpt) : undefined;
            this.copyAtt(resOpt, copy);
            return copy;
        }
        // return p.measure(bodyCode);
    }
    validate() {
        // let bodyCode = () =>
        {
            const missingFields = [];
            if (!this.name) {
                missingFields.push('name');
            }
            if (this.cardinality) {
                if (!this.cardinality.minimum) {
                    missingFields.push('cardinality.minimum');
                }
                if (!this.cardinality.maximum) {
                    missingFields.push('cardinality.maximum');
                }
            }
            if (missingFields.length > 0) {
                internal_1.Logger.error(this.ctx, this.TAG, this.validate.name, this.atCorpusPath, internal_1.cdmLogCode.ErrValdnIntegrityCheckFailure, this.atCorpusPath, missingFields.map((s) => `'${s}'`).join(', '));
                return false;
            }
            if (this.cardinality) {
                if (!internal_1.CardinalitySettings.isMinimumValid(this.cardinality.minimum)) {
                    internal_1.Logger.error(this.ctx, this.TAG, this.validate.name, this.atCorpusPath, internal_1.cdmLogCode.ErrValdnInvalidMinCardinality, this.cardinality.minimum);
                    return false;
                }
                if (!internal_1.CardinalitySettings.isMaximumValid(this.cardinality.maximum)) {
                    internal_1.Logger.error(this.ctx, this.TAG, this.validate.name, this.atCorpusPath, internal_1.cdmLogCode.ErrValdnInvalidMaxCardinality, this.cardinality.maximum);
                    return false;
                }
            }
            return true;
        }
        // return p.measure(bodyCode);
    }
    isDerivedFrom(base, resOpt) {
        // let bodyCode = () =>
        {
            return false;
        }
        // return p.measure(bodyCode);
    }
    visit(pathFrom, preChildren, postChildren) {
        // let bodyCode = () =>
        {
            const path = this.fetchDeclaredPath(pathFrom);
            if (preChildren && preChildren(this, path)) {
                return false;
            }
            if (this.dataType) {
                if (this.dataType.visit(`${path}/dataType/`, preChildren, postChildren)) {
                    return true;
                }
            }
            if (this.attributeContext) {
                if (this.attributeContext.visit(`${path}/attributeContext/`, preChildren, postChildren)) {
                    return true;
                }
            }
            if (this.projection) {
                if (this.projection.visit(`${path}/projection/`, preChildren, postChildren)) {
                    return true;
                }
            }
            if (this.visitAtt(path, preChildren, postChildren)) {
                return true;
            }
            if (postChildren && postChildren(this, path)) {
                return true;
            }
            return false;
        }
        // return p.measure(bodyCode);
    }
    /**
     * @internal
     */
    constructResolvedTraits(rtsb, resOpt) {
        // let bodyCode = () =>
        {
            // get from datatype
            if (this.dataType) {
                rtsb.takeReference(this.dataType
                    .fetchResolvedTraits(resOpt));
            }
            // get from purpose
            if (this.purpose) {
                rtsb.mergeTraits(this.purpose
                    .fetchResolvedTraits(resOpt));
            }
            this.addResolvedTraitsApplied(rtsb, resOpt);
            // special case for attributes, replace a default "this.attribute" with this attribute on traits that elevate attribute
            if (rtsb.rts && rtsb.rts.hasElevated) {
                const replacement = new internal_1.CdmAttributeReference(this.ctx, this.name, true);
                replacement.ctx = this.ctx;
                replacement.explicitReference = this.copy();
                replacement.inDocument = this.inDocument;
                replacement.owner = this;
                rtsb.replaceTraitParameterValue(resOpt, 'does.elevateAttribute', 'attribute', 'this.attribute', replacement);
            }
            // rtsb.cleanUp();
        }
        // return p.measure(bodyCode);
    }
    /**
     * @internal
     */
    constructResolvedAttributes(resOpt, under) {
        // let bodyCode = () =>
        {
            // find and cache the complete set of attributes
            // attributes definitions originate from and then get modified by subsequent re-defintions from (in this order):
            // the datatype used as an attribute, traits applied to that datatype,
            // the purpose of the attribute, any traits applied to the attribute.
            const rasb = new internal_1.ResolvedAttributeSetBuilder();
            rasb.ras.setAttributeContext(under);
            // add this attribute to the set
            // make a new one and apply any traits
            const newAtt = new internal_1.ResolvedAttribute(resOpt, this, this.name, under);
            rasb.ownOne(newAtt);
            const rts = this.fetchResolvedTraits(resOpt);
            if (this.owner && this.owner.objectType == internal_1.cdmObjectType.entityDef) {
                rasb.ras.setTargetOwner(this.owner);
            }
            if (this.projection) {
                rasb.ras.applyTraits(rts);
                const projDirective = new internal_1.ProjectionDirective(resOpt, this);
                const projCtx = this.projection.constructProjectionContext(projDirective, under, rasb.ras);
                const ras = this.projection.extractResolvedAttributes(projCtx, under);
                rasb.ras = ras;
            }
            else {
                // using resolution guidance
                // this context object holds all of the info about what needs to happen to resolve these attributes.
                // make a copy and add defaults if missing
                let resGuideWithDefault;
                if (this.resolutionGuidance !== undefined) {
                    resOpt.usedResolutionGuidance = true;
                    resGuideWithDefault = this.resolutionGuidance.copy(resOpt);
                }
                else {
                    resGuideWithDefault = new internal_1.CdmAttributeResolutionGuidance(this.ctx);
                }
                // renameFormat is not currently supported for type attributes
                resGuideWithDefault.renameFormat = undefined;
                resGuideWithDefault.updateAttributeDefaults(undefined, this);
                const arc = new internal_1.AttributeResolutionContext(resOpt, resGuideWithDefault, rts);
                // from the traits of the datatype, purpose and applied here, see if new attributes get generated
                rasb.applyTraits(arc);
                rasb.generateApplierAttributes(arc, false); // false = don't apply these traits to added things
                // this may have added symbols to the dependencies, so merge them
                resOpt.symbolRefSet.merge(arc.resOpt.symbolRefSet);
            }
            return rasb;
        }
        // return p.measure(bodyCode);
    }
    /**
     * @deprecated
     * For internal use only.
     */
    fetchResolvedEntityReference(resOpt) {
        // let bodyCode = () =>
        {
            return undefined;
        }
        // return p.measure(bodyCode);
    }
}
exports.CdmTypeAttributeDefinition = CdmTypeAttributeDefinition;
//# sourceMappingURL=CdmTypeAttributeDefinition.js.map