"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.CdmAttributeResolutionGuidance = void 0;
const internal_1 = require("../internal");
/**
 * @deprecated
 * Resolution guidance is being deprecated in favor of Projections. https://docs.microsoft.com/en-us/common-data-model/sdk/convert-logical-entities-resolved-entities#projection-overview
 */
class CdmAttributeResolutionGuidance extends internal_1.cdmObjectSimple {
    constructor(ctx) {
        super(ctx);
        // let bodyCode = () =>
        {
            this.objectType = internal_1.cdmObjectType.attributeResolutionGuidanceDef;
        }
        // return p.measure(bodyCode);
    }
    static get objectType() {
        return internal_1.cdmObjectType.attributeResolutionGuidanceDef;
    }
    getObjectType() {
        // let bodyCode = () =>
        {
            return internal_1.cdmObjectType.attributeResolutionGuidanceDef;
        }
        // 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 CdmAttributeResolutionGuidance(this.ctx);
            }
            else {
                copy = host;
                copy.ctx = this.ctx;
                // clear any values that may hvae been in host
                copy.expansion = undefined;
                copy.entityByReference = undefined;
                copy.selectsSubAttribute = undefined;
            }
            copy.removeAttribute = this.removeAttribute;
            copy.imposedDirectives = this.imposedDirectives ? this.imposedDirectives.slice() : undefined;
            copy.removedDirectives = this.removedDirectives ? this.removedDirectives.slice() : undefined;
            copy.addSupportingAttribute = this.addSupportingAttribute ? this.addSupportingAttribute.copy(resOpt) : undefined;
            copy.cardinality = this.cardinality;
            copy.renameFormat = this.renameFormat;
            if (this.expansion) {
                copy.expansion = {};
                copy.expansion.startingOrdinal = this.expansion.startingOrdinal;
                copy.expansion.maximumExpansion = this.expansion.maximumExpansion;
                copy.expansion.countAttribute = this.expansion.countAttribute;
            }
            if (this.entityByReference) {
                copy.entityByReference = {};
                copy.entityByReference.alwaysIncludeForeignKey = this.entityByReference.alwaysIncludeForeignKey;
                copy.entityByReference.referenceOnlyAfterDepth = this.entityByReference.referenceOnlyAfterDepth;
                copy.entityByReference.foreignKeyAttribute = this.entityByReference.foreignKeyAttribute;
                copy.entityByReference.allowReference = this.entityByReference.allowReference;
            }
            if (this.selectsSubAttribute) {
                copy.selectsSubAttribute = {};
                copy.selectsSubAttribute.selects = this.selectsSubAttribute.selects;
                copy.selectsSubAttribute.selectedTypeAttribute = this.selectsSubAttribute.selectedTypeAttribute;
                copy.selectsSubAttribute.selectsSomeTakeNames = this.selectsSubAttribute.selectsSomeTakeNames;
                copy.selectsSubAttribute.selectsSomeAvoidNames = this.selectsSubAttribute.selectsSomeAvoidNames;
            }
            return copy;
        }
        // return p.measure(bodyCode);
    }
    /**
     * @internal
     */
    updateAttributeDefaults(attName, owner) {
        // handle the cardinality and expansion group.
        // default is one, but if there is some hint of an array, make it work
        if (this.cardinality === undefined) {
            if (this.expansion !== undefined) {
                this.cardinality = 'many';
            }
            else {
                this.cardinality = 'one';
            }
        }
        if (this.cardinality === 'many' && this.expansion === undefined) {
            this.expansion = {};
        }
        if (this.cardinality === 'many' && this.expansion !== undefined) {
            if (this.expansion.startingOrdinal === undefined) {
                this.expansion.startingOrdinal = 0;
            }
            if (this.expansion.maximumExpansion === undefined) {
                this.expansion.maximumExpansion = 5;
            }
            if (this.expansion.countAttribute === undefined) {
                this.expansion.countAttribute = this.ctx.corpus.fetchArtifactAttribute('count');
                this.expansion.countAttribute.owner = owner;
                this.expansion.countAttribute.inDocument = owner.inDocument;
            }
        }
        // entity by ref. anything mentioned?
        if (this.entityByReference) {
            if (this.entityByReference.allowReference === undefined) {
                this.entityByReference.allowReference = true;
            }
            if (this.entityByReference.allowReference) {
                if (this.entityByReference.alwaysIncludeForeignKey === undefined) {
                    this.entityByReference.alwaysIncludeForeignKey = false;
                }
                if (this.entityByReference.foreignKeyAttribute === undefined) {
                    // make up a fk
                    this.entityByReference.foreignKeyAttribute = this.ctx.corpus.fetchArtifactAttribute('id');
                    this.entityByReference.foreignKeyAttribute.owner = owner;
                    this.entityByReference.foreignKeyAttribute.inDocument = owner.inDocument;
                }
            }
        }
        // selects one>
        if (this.selectsSubAttribute) {
            if (this.selectsSubAttribute.selects === undefined) {
                this.selectsSubAttribute.selects = 'one';
            }
            if (this.selectsSubAttribute.selects === 'one') {
                if (this.selectsSubAttribute.selectedTypeAttribute === undefined) {
                    // make up a type indicator
                    this.selectsSubAttribute.selectedTypeAttribute = this.ctx.corpus.fetchArtifactAttribute('type');
                    this.selectsSubAttribute.selectedTypeAttribute.owner = owner;
                    this.selectsSubAttribute.selectedTypeAttribute.inDocument = owner.inDocument;
                }
            }
        }
        // only set a rename format if one is needed for arrays or added atts
        if (this.renameFormat === undefined) {
            if (attName === undefined) { // a type attribute, so no nesting
                if (this.cardinality === 'many') {
                    this.renameFormat = '{a}{o}';
                }
            }
            else {
                if (this.cardinality === 'many') {
                    this.renameFormat = '{a}{o}{M}';
                }
                else {
                    this.renameFormat = '{a}{M}';
                }
            }
        }
        if (this.renameFormat !== undefined) {
            // rename format is a lie. actually only supports sub-attribute name and ordinal as 'a' and 'o'
            if (attName !== undefined) {
                // replace the use of {a or A} with the outer attributeName
                let upper = false;
                let iA = this.renameFormat.indexOf('{a}');
                if (iA < 0) {
                    iA = this.renameFormat.indexOf('{A}');
                    upper = true;
                }
                if (iA >= 0) {
                    if (upper) {
                        attName = attName.charAt(0).toUpperCase() + attName.slice(1);
                    }
                    this.renameFormat = this.renameFormat.slice(0, iA) + attName + this.renameFormat.slice(iA + 3);
                }
                // now, use of {m/M} should be turned to {a/A}
                let iM = this.renameFormat.indexOf('{m}');
                if (iM >= 0) {
                    this.renameFormat = this.renameFormat.slice(0, iM) + '{a}' + this.renameFormat.slice(iM + 3);
                }
                else {
                    iM = this.renameFormat.indexOf('{M}');
                    if (iM >= 0) {
                        this.renameFormat = this.renameFormat.slice(0, iM) + '{A}' + this.renameFormat.slice(iM + 3);
                    }
                }
            }
        }
    }
    validate() {
        // let bodyCode = () =>
        {
            return true;
        }
        // return p.measure(bodyCode);
    }
    visit(pathFrom, preChildren, postChildren) {
        // let bodyCode = () =>
        {
            if (preChildren && preChildren(this, pathFrom)) {
                return false;
            }
            if (this.addSupportingAttribute) {
                if (this.addSupportingAttribute.visit(`${pathFrom}addSupportingAttribute/`, preChildren, postChildren)) {
                    return true;
                }
            }
            if (this.expansion && this.expansion.countAttribute) {
                if (this.expansion.countAttribute.visit(`${pathFrom}countAttribute/`, preChildren, postChildren)) {
                    return true;
                }
            }
            if (this.entityByReference && this.entityByReference.foreignKeyAttribute) {
                if (this.entityByReference.foreignKeyAttribute.visit(`${pathFrom}foreignKeyAttribute/`, preChildren, postChildren)) {
                    return true;
                }
            }
            if (this.selectsSubAttribute && this.selectsSubAttribute.selectedTypeAttribute) {
                if (this.selectsSubAttribute.selectedTypeAttribute.visit(`${pathFrom}selectedTypeAttribute/`, preChildren, postChildren)) {
                    return true;
                }
            }
            if (postChildren && postChildren(this, pathFrom)) {
                return true;
            }
            return false;
        }
        // return p.measure(bodyCode);
    }
    /**
     * @internal
     */
    combineResolutionGuidance(addIn) {
        const startWith = this;
        if (!addIn) {
            return startWith;
        }
        if (!startWith) {
            return addIn;
        }
        const result = new CdmAttributeResolutionGuidance(this.ctx);
        // can remove and then un-remove later
        if (startWith.removeAttribute === true) {
            if (addIn.removeAttribute === undefined || addIn.removeAttribute === true) {
                result.removeAttribute = true;
            }
        }
        else {
            if (addIn.removeAttribute !== undefined && addIn.removeAttribute === true) {
                result.removeAttribute = true;
            }
        }
        // copy and combine if needed
        if (addIn.imposedDirectives) {
            if (startWith.imposedDirectives) {
                result.imposedDirectives = startWith.imposedDirectives.slice();
            }
            else {
                result.imposedDirectives = [];
            }
            result.imposedDirectives.concat(addIn.imposedDirectives);
        }
        else {
            result.imposedDirectives = startWith.imposedDirectives;
        }
        if (addIn.removedDirectives) {
            if (startWith.removedDirectives) {
                result.removedDirectives = startWith.removedDirectives.slice();
            }
            else {
                result.removedDirectives = [];
            }
            result.removedDirectives.concat(addIn.removedDirectives);
        }
        else {
            result.removedDirectives = startWith.removedDirectives;
        }
        result.addSupportingAttribute = startWith.addSupportingAttribute;
        if (addIn.addSupportingAttribute) {
            result.addSupportingAttribute = addIn.addSupportingAttribute;
        }
        result.cardinality = startWith.cardinality;
        if (addIn.cardinality) {
            result.cardinality = addIn.cardinality;
        }
        result.renameFormat = startWith.renameFormat;
        if (addIn.renameFormat) {
            result.renameFormat = addIn.renameFormat;
        }
        // for these sub objects, ok to just use the same objects unless something is combined. assumption is that these are static during the resolution
        if (addIn.expansion) {
            if (startWith.expansion) {
                result.expansion = {};
                result.expansion.startingOrdinal = startWith.expansion.startingOrdinal;
                if (addIn.expansion.startingOrdinal !== undefined) {
                    result.expansion.startingOrdinal = addIn.expansion.startingOrdinal;
                }
                result.expansion.maximumExpansion = startWith.expansion.maximumExpansion;
                if (addIn.expansion.maximumExpansion !== undefined) {
                    result.expansion.maximumExpansion = addIn.expansion.maximumExpansion;
                }
                result.expansion.countAttribute = startWith.expansion.countAttribute;
                if (addIn.expansion.countAttribute !== undefined) {
                    result.expansion.countAttribute = addIn.expansion.countAttribute;
                }
            }
            else {
                result.expansion = addIn.expansion;
            }
        }
        else {
            result.expansion = startWith.expansion;
        }
        if (addIn.entityByReference) {
            if (startWith.entityByReference) {
                result.entityByReference = {};
                result.entityByReference.alwaysIncludeForeignKey = startWith.entityByReference.alwaysIncludeForeignKey;
                if (addIn.entityByReference.alwaysIncludeForeignKey !== undefined) {
                    result.entityByReference.alwaysIncludeForeignKey = addIn.entityByReference.alwaysIncludeForeignKey;
                }
                result.entityByReference.referenceOnlyAfterDepth = startWith.entityByReference.referenceOnlyAfterDepth;
                if (addIn.entityByReference.referenceOnlyAfterDepth !== undefined) {
                    result.entityByReference.referenceOnlyAfterDepth = addIn.entityByReference.referenceOnlyAfterDepth;
                }
                result.entityByReference.foreignKeyAttribute = startWith.entityByReference.foreignKeyAttribute;
                if (addIn.entityByReference.foreignKeyAttribute !== undefined) {
                    result.entityByReference.foreignKeyAttribute = addIn.entityByReference.foreignKeyAttribute;
                }
                result.entityByReference.allowReference = startWith.entityByReference.allowReference;
                if (addIn.entityByReference.allowReference !== undefined) {
                    result.entityByReference.allowReference = addIn.entityByReference.allowReference;
                }
            }
            else {
                result.entityByReference = addIn.entityByReference;
            }
        }
        else {
            result.entityByReference = startWith.entityByReference;
        }
        if (addIn.selectsSubAttribute) {
            if (startWith.selectsSubAttribute) {
                result.selectsSubAttribute = {};
                result.selectsSubAttribute.selectedTypeAttribute = startWith.selectsSubAttribute.selectedTypeAttribute;
                if (addIn.selectsSubAttribute.selectedTypeAttribute !== undefined) {
                    result.selectsSubAttribute.selectedTypeAttribute = addIn.selectsSubAttribute.selectedTypeAttribute;
                }
                result.selectsSubAttribute.selects = startWith.selectsSubAttribute.selects;
                if (addIn.selectsSubAttribute.selects !== undefined) {
                    result.selectsSubAttribute.selects = addIn.selectsSubAttribute.selects;
                }
                if (addIn.selectsSubAttribute.selectsSomeTakeNames) {
                    if (startWith.selectsSubAttribute.selectsSomeTakeNames) {
                        result.selectsSubAttribute.selectsSomeTakeNames = [...(startWith.selectsSubAttribute.selectsSomeTakeNames)];
                    }
                    else {
                        result.selectsSubAttribute.selectsSomeTakeNames = [];
                    }
                    result.selectsSubAttribute.selectsSomeTakeNames.concat(addIn.selectsSubAttribute.selectsSomeTakeNames);
                }
                if (addIn.selectsSubAttribute.selectsSomeAvoidNames) {
                    if (startWith.selectsSubAttribute.selectsSomeAvoidNames) {
                        result.selectsSubAttribute.selectsSomeAvoidNames = [...(startWith.selectsSubAttribute.selectsSomeAvoidNames)];
                    }
                    else {
                        result.selectsSubAttribute.selectsSomeAvoidNames = [];
                    }
                    result.selectsSubAttribute.selectsSomeAvoidNames.concat(addIn.selectsSubAttribute.selectsSomeAvoidNames);
                }
            }
            else {
                result.selectsSubAttribute = addIn.selectsSubAttribute;
            }
        }
        else {
            result.selectsSubAttribute = startWith.selectsSubAttribute;
        }
        return result;
    }
}
exports.CdmAttributeResolutionGuidance = CdmAttributeResolutionGuidance;
//# sourceMappingURL=CdmAttributeResolutionGuidance.js.map