"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.CdmObjectDefinitionBase = void 0;
const internal_1 = require("../internal");
class CdmObjectDefinitionBase extends internal_1.CdmObjectBase {
    // baseCache : Set<string>;
    constructor(ctx) {
        super(ctx);
        this.exhibitsTraits = new internal_1.CdmTraitCollection(this.ctx, this);
    }
    /**
     * @internal
     */
    copyDef(resOpt, copy) {
        // let bodyCode = () =>
        {
            copy.ctx = this.ctx;
            copy.declaredPath = this.declaredPath;
            copy.explanation = this.explanation;
            copy.exhibitsTraits.clear();
            for (const trait of this.exhibitsTraits) {
                copy.exhibitsTraits.push(trait);
            }
            copy.inDocument = this.inDocument; // if gets put into a new document, this will change. until, use the source
        }
        // return p.measure(bodyCode);
    }
    /**
     * @internal
     * Creates a 'portable' reference object to this object. portable means there is no symbolic name set until this reference is placed
     * into some final document.
     */
    createPortableReference(resOpt) {
        const cdmObjectRef = this.ctx.corpus.MakeObject(internal_1.CdmCorpusDefinition.mapReferenceType(this.objectType), 'portable', true);
        cdmObjectRef.portableReference = this;
        cdmObjectRef.inDocument = this.inDocument; // where it started life
        cdmObjectRef.owner = this.owner;
        return cdmObjectRef;
    }
    fetchObjectDefinitionName() {
        // let bodyCode = () =>
        {
            return this.getName();
        }
        // return p.measure(bodyCode);
    }
    fetchObjectDefinition(resOpt) {
        // let bodyCode = () =>
        {
            if (!resOpt) {
                resOpt = new internal_1.resolveOptions(this, this.ctx.corpus.defaultResolutionDirectives);
            }
            resOpt.fromMoniker = undefined;
            return this;
        }
        // return p.measure(bodyCode);
    }
    /**
     * @internal
     */
    visitDef(pathFrom, preChildren, postChildren) {
        // let bodyCode = () =>
        {
            if (this.exhibitsTraits) {
                if (this.exhibitsTraits.visitArray(`${pathFrom}/exhibitsTraits/`, preChildren, postChildren)) {
                    return true;
                }
            }
            return false;
        }
        // return p.measure(bodyCode);
    }
    /**
     * Given an initial path, returns this object's declared path
     * @internal
     */
    fetchDeclaredPath(pathFrom) {
        var _a;
        return (_a = pathFrom + this.getName()) !== null && _a !== void 0 ? _a : '';
    }
    /**
     * @internal
     */
    isDerivedFromDef(resOpt, baseCdmObjectRef, name, seek) {
        // let bodyCode = () =>
        {
            if (seek === name) {
                return true;
            }
            const def = baseCdmObjectRef ? baseCdmObjectRef.fetchObjectDefinition(resOpt) : undefined;
            // detects a direct definition cycle, doesn't work for cases like A->B->A.
            if (def === this) {
                internal_1.Logger.error(this.ctx, CdmObjectDefinitionBase.name, this.isDerivedFromDef.name, this.atCorpusPath, internal_1.cdmLogCode.ErrCycleInObjectDefinition);
                return true;
            }
            if (def) {
                return def.isDerivedFrom(seek, resOpt);
            }
            return false;
        }
        // return p.measure(bodyCode);
    }
    /**
     * @internal
     */
    constructResolvedTraitsDef(baseCdmObjectRef, rtsb, resOpt) {
        // let bodyCode = () =>
        {
            // get from base class first, then see if some are applied to base class on ref then add any traits exhibited by this def
            if (baseCdmObjectRef) {
                // merge in all from base class
                rtsb.mergeTraits(baseCdmObjectRef.fetchResolvedTraits(resOpt));
            }
            // merge in any that are exhibited by this class
            if (this.exhibitsTraits) {
                for (const et of this.exhibitsTraits) {
                    rtsb.mergeTraits(et.fetchResolvedTraits(resOpt));
                }
            }
        }
        // return p.measure(bodyCode);
    }
    /**
     * @internal
     */
    getObjectPath() {
        // let bodyCode = () =>
        {
            return this.atCorpusPath;
        }
        // return p.measure(bodyCode);
    }
    createSimpleReference(resOpt) {
        if (!resOpt) {
            resOpt = new internal_1.resolveOptions(this, this.ctx.corpus.defaultResolutionDirectives);
        }
        let name;
        if (this.declaredPath) {
            name = this.declaredPath;
        }
        else {
            name = this.getName();
        }
        const cdmObjectRef = this.ctx.corpus.MakeObject(internal_1.CdmCorpusDefinition.mapReferenceType(this.objectType), name, true);
        if (resOpt.saveResolutionsOnCopy) {
            // used to localize references between documents
            cdmObjectRef.explicitReference = this;
            cdmObjectRef.inDocument = this.inDocument;
        }
        return cdmObjectRef;
    }
}
exports.CdmObjectDefinitionBase = CdmObjectDefinitionBase;
//# sourceMappingURL=CdmObjectDefinitionBase.js.map