"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module Elements
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.RepositoryLink = exports.FolderLink = exports.UrlLink = exports.LinkElement = exports.GroupInformationElement = exports.SheetIndexPartition = exports.SpatialLocationPartition = exports.PhysicalPartition = exports.LinkPartition = exports.InformationRecordPartition = exports.GraphicalPartition3d = exports.GroupInformationPartition = exports.DocumentPartition = exports.DefinitionPartition = exports.InformationPartitionElement = exports.TemplateRecipe2d = exports.GraphicalType2d = exports.TemplateRecipe3d = exports.SpatialLocationType = exports.PhysicalType = exports.RecipeDefinitionElement = exports.TypeDefinitionElement = exports.DefinitionGroup = exports.DefinitionContainer = exports.DefinitionSet = exports.DefinitionElement = exports.InformationRecordElement = exports.Sheet = exports.SheetTemplate = exports.SheetBorderTemplate = exports.SectionDrawing = exports.Drawing = exports.Document = exports.Subject = exports.InformationReferenceElement = exports.DriverBundleElement = exports.InformationContentElement = exports.SectionDrawingLocation = exports.VolumeElement = exports.SpatialLocationElement = exports.PhysicalElement = exports.SpatialElement = exports.DrawingGraphic = exports.AnnotationElement2d = exports.GraphicalElement2d = exports.GeometricElement2d = exports.GraphicalElement3d = exports.GeometricElement3d = exports.GeometricElement = exports.Element = void 0;
exports.ProjectInformationRecord = exports.RenderTimeline = exports.LineStyle = exports.GeometryPart = exports.RoleElement = exports.EmbeddedFileLink = void 0;
const core_bentley_1 = require("@itwin/core-bentley");
const core_common_1 = require("@itwin/core-common");
const core_geometry_1 = require("@itwin/core-geometry");
const Entity_1 = require("./Entity");
const EditTxn_1 = require("./EditTxn");
const Model_1 = require("./Model");
const NavigationRelationship_1 = require("./NavigationRelationship");
const Symbols_1 = require("./internal/Symbols");
const ecschema_metadata_1 = require("@itwin/ecschema-metadata");
/** The smallest individually identifiable building block for modeling the real world in an iModel.
 * Each element represents an [[Entity]] in the real world. Sets of Elements (contained in [[Model]]s) are used to model
 * other Elements that represent larger scale real world entities. Using this recursive modeling strategy,
 * Elements can represent entities at any scale. Elements can represent physical things or abstract concepts
 * or simply be information records.
 *
 * Every Element has a 64-bit id (inherited from Entity) that uniquely identifies it within an iModel. Every Element also
 * has a [[code]] that identifies its meaning in the real world. Additionally, Elements may have a [[federationGuid]]
 * to hold a GUID, if the element was assigned that GUID by some other federated database. The iModel database enforces
 * uniqueness of id, code, and federationGuid.
 *
 * The Element class provides `static` methods like [[onInsert]], [[onUpdated]], [[onCloned]], and [[onChildAdded]] that enable
 * it to customize persistence operations. For example, the base implementations of [[onInsert]], [[onUpdate]], and [[onDelete]]
 * validate that the appropriate [locks]($docs/learning/backend/ConcurrencyControl.md), [codes]($docs/learning/backend/CodeService.md),
 * and [channel permissions]($docs/learning/backend/Channel.md) are obtained before a change to the element is written to the iModel.
 * A subclass of Element that overrides any of these methods **must** call the `super` method as well. An application that supplies its
 * own Element subclasses should register them at startup via [[ClassRegistry.registerModule]] or [[ClassRegistry.register]].
 *
 * See:
 * * [Element Fundamentals]($docs/bis/guide/fundamentals/element-fundamentals.md)
 * * [Working with schemas and elements in TypeScript]($docs/learning/backend/SchemasAndElementsInTypeScript.md)
 * * [Creating elements]($docs/learning/backend/CreateElements.md)
 * @public @preview
 */
class Element extends Entity_1.Entity {
    static get className() { return "Element"; }
    /** @internal */
    static get protectedOperations() { return ["onInsert", "onUpdate", "onDelete"]; }
    /** The ModelId of the [Model]($docs/bis/guide/fundamentals/model-fundamentals.md) containing this element */
    model;
    /** The [Code]($docs/bis/guide/fundamentals/codes.md) for this element */
    code;
    /** The parent element, if present, of this element. */
    parent;
    /** A [FederationGuid]($docs/bis/guide/fundamentals/element-fundamentals.md#federationguid) assigned to this element by some other federated database */
    federationGuid;
    /** A [user-assigned label]($docs/bis/guide/fundamentals/element-fundamentals.md#userlabel) for this element. */
    userLabel;
    /** Optional [json properties]($docs/bis/guide/fundamentals/element-fundamentals.md#jsonproperties) of this element. */
    jsonProperties;
    constructor(props, iModel) {
        super(props, iModel);
        this.code = core_common_1.Code.fromJSON(props.code); // TODO: Validate props.code - don't silently fail if it is the wrong type
        this.model = core_common_1.RelatedElement.idFromJson(props.model);
        this.parent = core_common_1.RelatedElement.fromJSON(props.parent);
        this.federationGuid = props.federationGuid;
        this.userLabel = props.userLabel;
        this.jsonProperties = { ...props.jsonProperties }; // make sure we have our own copy
    }
    /**
     * Element custom HandledProps include 'codeValue', 'codeSpec', 'codeScope', 'model', 'parent', 'federationGuid', and 'lastMod'.
     * @inheritdoc
     * @beta
     */
    static _customHandledProps = [
        { propertyName: "codeValue", source: "Class" },
        { propertyName: "codeSpec", source: "Class" },
        { propertyName: "codeScope", source: "Class" },
        { propertyName: "model", source: "Class" },
        { propertyName: "parent", source: "Class" },
        { propertyName: "federationGuid", source: "Class" },
        { propertyName: "lastMod", source: "Class" },
    ];
    /**
     * Element deserializes 'codeValue', 'codeSpec', 'codeScope', 'model', 'parent', and 'federationGuid'.
     * @inheritdoc
     * @beta
     */
    static deserialize(props) {
        const elProps = super.deserialize(props);
        const instance = props.row;
        elProps.code = { value: instance.codeValue ?? "", spec: instance.codeSpec.id, scope: instance.codeScope.id };
        elProps.model = instance.model.id;
        if (instance.parent)
            elProps.parent = instance.parent;
        if (instance.federationGuid)
            elProps.federationGuid = instance.federationGuid;
        return elProps;
    }
    /**
     * Element serialize 'codeValue', 'codeSpec', 'codeScope', 'model', 'parent', and 'federationGuid'.
     * @inheritdoc
     * @beta
     */
    static serialize(props, iModel) {
        const inst = super.serialize(props, iModel);
        inst.codeValue = props.code.value;
        inst.codeSpec = { id: props.code.spec };
        inst.codeScope = { id: props.code.scope };
        inst.model = { id: props.model };
        inst.parent = props.parent;
        inst.federationGuid = props.federationGuid ?? iModel[Symbols_1._nativeDb].newBeGuid();
        return inst;
    }
    /** Called before a new Element is inserted.
     * @note throw an exception to disallow the insert
     * @note If you override this method, you must call super.
     * @note `this` is the class of the Element to be inserted
     * @beta
     */
    static onInsert(arg) {
        const { iModel, props } = arg;
        const operation = "insert";
        iModel.channels[Symbols_1._verifyChannel](arg.props.model);
        iModel.locks.checkSharedLock(props.model, "model", operation); // inserting requires shared lock on model
        if (props.parent) // inserting requires shared lock on parent, if present
            iModel.locks.checkSharedLock(props.parent.id, "parent", operation);
        iModel.codeService?.verifyCode(arg);
    }
    /** Called after a new Element was inserted.
     * @note If you override this method, you must call super.
     * @note `this` is the class of the Element that was inserted
     * @beta
     */
    static onInserted(arg) {
        const locks = arg.iModel.locks;
        if (locks && !locks.holdsExclusiveLock(arg.model))
            locks[Symbols_1._elementWasCreated](arg.id);
        arg.iModel.models[Symbols_1._cache].delete(arg.model);
    }
    /** Called before an Element is updated.
     * @note throw an exception to disallow the update
     * @note If you override this method, you must call super.
     * @note `this` is the class of the Element to be updated
     * @beta
     */
    static onUpdate(arg) {
        const { iModel, props } = arg;
        iModel.channels[Symbols_1._verifyChannel](props.model);
        iModel.locks.checkExclusiveLock(props.id, "element", "update"); // eslint-disable-line @typescript-eslint/no-non-null-assertion
        iModel.codeService?.verifyCode(arg);
    }
    /** Called after an Element was updated.
     * @note If you override this method, you must call super.
     * @note `this` is the class of the Element that was updated
     * @beta
     */
    static onUpdated(arg) {
        arg.iModel.elements[Symbols_1._cache].delete({ id: arg.id });
        arg.iModel.models[Symbols_1._cache].delete(arg.model);
    }
    /** Called before an Element is deleted.
     * @note throw an exception to disallow the delete
     * @note If you override this method, you must call super.
     * @note `this` is the class of the Element to be deleted
     * @beta
     */
    static onDelete(arg) {
        arg.iModel.channels[Symbols_1._verifyChannel](arg.model);
        arg.iModel.locks.checkExclusiveLock(arg.id, "element", "delete");
    }
    /** Called after an Element was deleted.
     * @note If you override this method, you must call super.
     * @note `this` is the class of the Element that was deleted
     * @beta
     */
    static onDeleted(arg) {
        arg.iModel.elements[Symbols_1._cache].delete(arg);
        arg.iModel.models[Symbols_1._cache].delete(arg.model);
    }
    /** Called after a batch of Elements of this class were deleted in a bulk delete operation.
     *
     * The default implementation fires all JS notifications that would normally be fired
     * per-element in the single-element delete path:
     * 1. **[[onDeleted]]** — for every element; preserves any user overrides.
     * 2. **[[onSubModelDelete]] + [[onSubModelDeleted]]** — for sub-model root elements
     *    (`subModelId` is set), matching the order of the single-element path.
     *
     * @note If you override this method, you must call super.
     * @note `this` is the class of the Elements that were deleted.
     * @beta
     */
    static onBulkDeleted(arg) {
        for (const el of arg.elements) {
            this.onDelete({ iModel: arg.iModel, id: el.id, model: el.model, federationGuid: el.federationGuid ?? "" });
            this.onDeleted({ iModel: arg.iModel, id: el.id, model: el.model, federationGuid: el.federationGuid ?? "" });
            if (el.subModelId !== undefined) {
                this.onSubModelDelete({ iModel: arg.iModel, subModelId: el.subModelId });
                this.onSubModelDeleted({ iModel: arg.iModel, subModelId: el.subModelId });
            }
        }
    }
    /** Called after a batch of child Elements of this class's instances were deleted in a bulk delete operation.
     *
     * The default implementation calls [[onChildDelete]] and [[onChildDeleted]] for every entry in the batch.
     *
     * @note If you override this method, you must call super.
     * @note `this` is the class of the *parent* Element whose children were deleted.
     * @beta
     */
    static onBulkChildDeleted(arg) {
        for (const el of arg.elements) {
            this.onChildDelete({ iModel: arg.iModel, parentId: el.parentId, childId: el.childId });
            this.onChildDeleted({ iModel: arg.iModel, parentId: el.parentId, childId: el.childId });
        }
    }
    /** Called when an element with an instance of this class as its parent is about to be deleted.
     * @note throw an exception if the element should not be deleted
     * @note implementers should not presume that the element was deleted if this method does not throw,
     * since the delete may fail for other reasons. Instead, rely on [[onChildDeleted]] for that purpose.
     * @note `this` is the class of the parent Element whose child will be deleted
     * @beta
     */
    static onChildDelete(_arg) { }
    /** Called after an element with an instance of this class as its parent was successfully deleted.
     * @note `this` is the class of the parent Element whose child was deleted
     * @beta
     */
    static onChildDeleted(arg) {
        arg.iModel.elements[Symbols_1._cache].delete({ id: arg.parentId });
        arg.iModel.elements[Symbols_1._cache].delete({ id: arg.childId });
    }
    /** Called when a *new element* with an instance of this class as its parent is about to be inserted.
     * @note throw an exception if the element should not be inserted
     * @note `this` is the class of the prospective parent Element.
     * @beta
     */
    static onChildInsert(_arg) { }
    /** Called after a *new element* with an instance of this class as its parent was inserted.
     * @note `this` is the class of the parent Element.
     * @beta
     */
    static onChildInserted(arg) {
        arg.iModel.elements[Symbols_1._cache].delete({ id: arg.parentId });
    }
    /** Called when an element with an instance of this class as its parent is about to be updated.
     * @note throw an exception if the element should not be updated
     * @note `this` is the class of the parent Element.
     * @beta
     */
    static onChildUpdate(_arg) { }
    /** Called after an element with an instance of this the class as its parent was updated.
     * @note `this` is the class of the parent Element.
     * @beta
     */
    static onChildUpdated(arg) {
        arg.iModel.elements[Symbols_1._cache].delete({ id: arg.parentId });
    }
    /** Called when an *existing element* is about to be updated so that an instance of this class will become its new parent.
     * @note throw an exception if the element should not be added
     * @note `this` is the class of the prospective parent Element.
     * @beta
     */
    static onChildAdd(_arg) { }
    /** Called after an *existing element* has been updated so that an instance of this class is its new parent.
     * @note `this` is the class of the new parent Element.
     * @beta
     */
    static onChildAdded(arg) {
        arg.iModel.elements[Symbols_1._cache].delete({ id: arg.parentId });
    }
    /** Called when an element with an instance of this class as its parent is about to be updated change to a different parent.
     * @note throw an exception if the element should not be dropped
     * @note `this` is the class of the parent Element.
     * @beta
     */
    static onChildDrop(_arg) { }
    /** Called after an element with an instance of this class as its previous parent was updated to have a new parent.
     * @note `this` is the class of the previous parent Element.
     * @beta
     */
    static onChildDropped(arg) {
        arg.iModel.elements[Symbols_1._cache].delete({ id: arg.parentId });
    }
    /** Called when an instance of this class is being *sub-modeled* by a new Model.
     * @note throw an exception if model should not be inserted
     * @note `this` is the class of Element to be sub-modeled.
     * @beta
     */
    static onSubModelInsert(_arg) { }
    /** Called after an instance of this class was *sub-modeled* by a new Model.
     * @note `this` is the class of Element that is now sub-modeled.
     * @beta
     */
    static onSubModelInserted(arg) {
        const id = arg.subModelId;
        arg.iModel.elements[Symbols_1._cache].delete({ id });
        arg.iModel.models[Symbols_1._cache].delete(id);
    }
    /** Called when a sub-model of an instance of this class is being deleted.
     * @note throw an exception if model should not be deleted
     * @note `this` is the class of Element that is sub-modeled.
     * @beta
     */
    static onSubModelDelete(_arg) { }
    /** Called after a sub-model of an instance of this class was deleted.
     * @note `this` is the class of Element that was sub-modeled.
     * @beta
     */
    static onSubModelDeleted(arg) {
        const id = arg.subModelId;
        arg.iModel.elements[Symbols_1._cache].delete({ id });
        arg.iModel.models[Symbols_1._cache].delete(id);
    }
    /** Called during the iModel transformation process after an Element from the source iModel was *cloned* for the target iModel.
     * The transformation process automatically handles remapping BisCore properties and those that are properly described in ECSchema.
     * This callback is only meant to be overridden if there are other Ids in non-standard locations that need to be remapped or other data that needs to be fixed up after the clone.
     * @param _context The context that persists any remapping between the source iModel and target iModel.
     * @param _sourceProps The ElementProps for the source Element that was cloned.
     * @param _targetProps The ElementProps that are a result of the clone. These can be further modified.
     * @note If you override this method, you must call super.
     * @beta
     */
    static onCloned(_context, _sourceProps, _targetProps) { }
    /** Called when a *root* element in a subgraph is changed and before its outputs are processed.
     * This special callback is made when:
     * * the element is part of an [[ElementDrivesElement]] graph, and
     * * the element has no inputs, and
     * * none of the element's outputs have been processed.
     * @see [[ElementDrivesElement]] for more on element dependency graphs.
     * @beta
     */
    static onBeforeOutputsHandledArg(arg) {
        // eslint-disable-next-line @typescript-eslint/no-deprecated
        this.onBeforeOutputsHandled(arg.elId, arg.iModel);
    }
    /** Called when a *root* element in a subgraph is changed and before its outputs are processed.
     * This special callback is made when:
     * * the element is part of an [[ElementDrivesElement]] graph, and
     * * the element has no inputs, and
     * * none of the element's outputs have been processed.
     * @see [[ElementDrivesElement]] for more on element dependency graphs.
     * @beta
     * @deprecated in 5.1.9 - will not be removed until after 2026-08-04. Use onBeforeOutputsHandledArg instead.
     */
    static onBeforeOutputsHandled(_id, _iModel) { }
    /** Called on an element in a graph after all of its inputs have been processed and before its outputs are processed.
     * This callback is made when:
     * * the specified element is part of an [[ElementDrivesElement]] graph, and
     * * there was a direct change to some element upstream in the dependency graph.
     * * all upstream elements in the graph have been processed.
     * * none of the downstream elements have been processed.
     * This method is not called if none of the element's inputs were changed.
     * @see [[ElementDrivesElement]] for more on element dependency graphs.
     * @beta
     */
    static onAllInputsHandledArg(arg) {
        // eslint-disable-next-line @typescript-eslint/no-deprecated
        this.onAllInputsHandled(arg.elId, arg.iModel);
    }
    /** Called on an element in a graph after all of its inputs have been processed and before its outputs are processed.
     * This callback is made when:
     * * the specified element is part of an [[ElementDrivesElement]] graph, and
     * * there was a direct change to some element upstream in the dependency graph.
     * * all upstream elements in the graph have been processed.
     * * none of the downstream elements have been processed.
     * This method is not called if none of the element's inputs were changed.
     * @see [[ElementDrivesElement]] for more on element dependency graphs.
     * @beta
     * @deprecated in 5.1.9 - will not be removed until after 2026-08-04. Use onAllInputsHandledArg instead.
     */
    static onAllInputsHandled(_id, _iModel) { }
    toJSON() {
        const val = super.toJSON();
        if (core_common_1.Code.isValid(this.code))
            val.code = this.code;
        val.model = this.model;
        if (undefined !== this.userLabel) // NOTE: blank string should be included in JSON
            val.userLabel = this.userLabel;
        if (this.federationGuid)
            val.federationGuid = this.federationGuid;
        if (this.parent)
            val.parent = this.parent;
        if (Object.keys(this.jsonProperties).length > 0)
            val.jsonProperties = this.jsonProperties;
        return val;
    }
    collectReferenceIds(referenceIds) {
        super.collectReferenceIds(referenceIds);
        referenceIds.addModel(this.model); // The modeledElement is a reference
        if (this.code.scope && core_bentley_1.Id64.isValidId64(this.code.scope))
            referenceIds.addElement(this.code.scope); // The element that scopes the code is a reference
        if (this.parent)
            referenceIds.addElement(this.parent.id); // A parent element is a reference
    }
    /** A *required reference* is an element that had to be inserted before this element could have been inserted.
     * This is the list of property keys on this element that store references to those elements
     * @note This should be overridden (with `super` called) at each level of the class hierarchy that introduces required references.
     * @note any property listed here must be added to the reference ids in [[collectReferenceIds]]
     * @beta
     */
    static requiredReferenceKeys = ["parent", "model"];
    /** A map of every [[requiredReferenceKeys]] on this class to their entity type.
     * @note This should be overridden (with `super` called) at each level of the class hierarchy that introduces required references.
     * @alpha
     */
    static requiredReferenceKeyTypeMap = {
        parent: core_common_1.ConcreteEntityTypes.Element,
        model: core_common_1.ConcreteEntityTypes.Model,
    };
    /** Get the class metadata for this element.
     * @deprecated in 5.0 - will not be removed until after 2026-06-13. Please use `getMetaData` provided by the parent class `Entity` instead.
     *
     * @example
     * ```typescript
     * // Current usage:
     * const metaData: EntityMetaData | undefined = element.getClassMetaData();
     *
     * // Replacement:
     * const metaData: EntityClass = await element.getMetaData();
     * ```
     */
    // eslint-disable-next-line @typescript-eslint/no-deprecated
    getClassMetaData() { return this.iModel.classMetaDataRegistry.find(this.classFullName); }
    /** Query metadata for this entity class from the iModel's schema. Returns cached metadata if available.*/
    async getMetaData() {
        if (this._metadata && ecschema_metadata_1.EntityClass.isEntityClass(this._metadata)) {
            return this._metadata;
        }
        const entity = await this.iModel.schemaContext.getSchemaItem(this.schemaItemKey, ecschema_metadata_1.EntityClass);
        if (entity !== undefined) {
            this._metadata = entity;
            return this._metadata;
        }
        else {
            throw new Error(`Cannot get metadata for ${this.classFullName}`);
        }
    }
    getAllUserProperties() {
        if (!this.jsonProperties.UserProps)
            this.jsonProperties.UserProps = new Object();
        return this.jsonProperties.UserProps;
    }
    /** Get a set of JSON user properties by namespace */
    getUserProperties(namespace) { return this.getAllUserProperties()[namespace]; }
    /** Change a set of user JSON properties of this Element by namespace. */
    setUserProperties(nameSpace, value) { this.getAllUserProperties()[nameSpace] = value; }
    /** Remove a set of JSON user properties, specified by namespace, from this Element */
    removeUserProperties(nameSpace) { delete this.getAllUserProperties()[nameSpace]; }
    /** Get a JSON property of this element, by namespace */
    getJsonProperty(nameSpace) { return this.jsonProperties[nameSpace]; }
    setJsonProperty(nameSpace, value) { this.jsonProperties[nameSpace] = value; }
    /** Get a display label for this Element. By default returns userLabel if present, otherwise code value. */
    getDisplayLabel() { return this.userLabel ?? this.code.value; }
    /** Get a list of HTML strings that describe this Element for the tooltip. Strings will be listed on separate lines in the tooltip.
     * Any instances of the pattern `%{tag}` will be replaced by the localized value of tag.
     */
    getToolTipMessage() {
        const addKey = (key) => `<b>%{iModelJs:Element.${key}}:</b> `; // %{iModelJs:Element.xxx} is replaced with localized value of xxx in frontend.
        const msg = [];
        const display = this.getDisplayLabel();
        msg.push(display ? display : `${addKey("Id") + this.id}, ${addKey("Type")}${this.className}`);
        if (this instanceof GeometricElement)
            msg.push(addKey("Category") + this.iModel.elements.getElement(this.category).getDisplayLabel());
        msg.push(addKey("Model") + this.iModel.elements.getElement(this.model).getDisplayLabel());
        return msg;
    }
    insert(txn) {
        return this.id = (txn ?? this.iModel[Symbols_1._implicitTxn]).insertElement(this.toJSON());
    }
    update(txn) {
        (txn ?? this.iModel[Symbols_1._implicitTxn]).updateElement(this.toJSON());
    }
    delete(txn) {
        (txn ?? this.iModel[Symbols_1._implicitTxn]).deleteElement(this.id);
    }
}
exports.Element = Element;
/** An abstract base class to model real world entities that intrinsically have geometry.
 * @public @preview
 */
class GeometricElement extends Element {
    static get className() { return "GeometricElement"; }
    /** The Id of the [[Category]] for this GeometricElement. */
    category;
    /** The GeometryStream for this GeometricElement. */
    geom;
    constructor(props, iModel) {
        super(props, iModel);
        this.category = core_bentley_1.Id64.fromJSON(props.category);
        this.geom = props.geom;
    }
    /** Type guard for instanceof [[GeometricElement3d]] */
    is3d() { return this instanceof GeometricElement3d; }
    /** Type guard for instanceof [[GeometricElement2d]] */
    is2d() { return this instanceof GeometricElement2d; }
    /** Get the [Transform]($geometry) from the Placement of this GeometricElement */
    getPlacementTransform() { return this.placement.transform; }
    calculateRange3d() { return this.placement.calculateRange(); }
    toJSON() {
        const val = super.toJSON();
        val.category = this.category;
        if (this.geom)
            val.geom = this.geom;
        return val;
    }
    collectReferenceIds(referenceIds) {
        super.collectReferenceIds(referenceIds);
        referenceIds.addElement(this.category);
        // TODO: GeometryPartIds?
    }
    /** @beta */
    static requiredReferenceKeys = [...super.requiredReferenceKeys, "category"];
    /** @alpha */
    static requiredReferenceKeyTypeMap = {
        ...super.requiredReferenceKeyTypeMap,
        category: core_common_1.ConcreteEntityTypes.Element,
    };
    /**
     * GeometricElement custom HandledProps includes 'inSpatialIndex'.
     * @inheritdoc
     * @beta
     */
    static _customHandledProps = [
        { propertyName: "inSpatialIndex", source: "Class" },
    ];
    /**
     * GeometricElement deserializes 'inSpatialIndex'.
     * @inheritdoc
     * @beta
     */
    static deserialize(props) {
        return super.deserialize(props);
    }
    /**
     * GeometricElement serialize 'inSpatialIndex'.
     * @inheritdoc
     * @beta
     */
    static serialize(props, iModel) {
        return super.serialize(props, iModel);
    }
}
exports.GeometricElement = GeometricElement;
/** An abstract base class to model real world entities that intrinsically have 3d geometry.
 * See [how to create a GeometricElement3d]($docs/learning/backend/CreateElements.md#GeometricElement3d).
 * @public @preview
 */
class GeometricElement3d extends GeometricElement {
    static get className() { return "GeometricElement3d"; }
    placement;
    typeDefinition;
    constructor(props, iModel) {
        super(props, iModel);
        this.placement = core_common_1.Placement3d.fromJSON(props.placement);
        if (props.typeDefinition)
            this.typeDefinition = core_common_1.TypeDefinition.fromJSON(props.typeDefinition);
    }
    toJSON() {
        const val = super.toJSON();
        val.placement = this.placement;
        if (undefined !== this.typeDefinition)
            val.typeDefinition = this.typeDefinition;
        return val;
    }
    collectReferenceIds(referenceIds) {
        super.collectReferenceIds(referenceIds);
        if (undefined !== this.typeDefinition)
            referenceIds.addElement(this.typeDefinition.id);
    }
    /**
     * GeometricElement3d custom HandledProps includes 'category', 'geometryStream', 'origin', 'yaw', 'pitch', 'roll',
     * 'bBoxLow', 'bBoxHigh', and 'typeDefinition'.
     * @inheritdoc
     * @beta
     */
    static _customHandledProps = [
        { propertyName: "category", source: "Class" },
        { propertyName: "geometryStream", source: "Class" },
        { propertyName: "origin", source: "Class" },
        { propertyName: "yaw", source: "Class" },
        { propertyName: "pitch", source: "Class" },
        { propertyName: "roll", source: "Class" },
        { propertyName: "bBoxLow", source: "Class" },
        { propertyName: "bBoxHigh", source: "Class" },
        { propertyName: "typeDefinition", source: "Class" }
    ];
    /**
     * GeometricElement3d deserializes 'category', 'geometryStream', 'origin', 'yaw', 'pitch', 'roll',
     * 'bBoxLow', 'bBoxHigh', and 'typeDefinition'.
     * @inheritdoc
     * @beta
     */
    static deserialize(props) {
        const elProps = super.deserialize(props);
        const instance = props.row;
        elProps.category = instance.category.id;
        const origin = instance.origin ? [instance.origin.x, instance.origin.y, instance.origin.z] : [0, 0, 0];
        let bbox;
        if ("bBoxHigh" in instance && instance.bBoxHigh !== undefined && "bBoxLow" in instance && instance.bBoxLow !== undefined) {
            bbox = {
                low: [instance.bBoxLow.x, instance.bBoxLow.y, instance.bBoxLow.z],
                high: [instance.bBoxHigh.x, instance.bBoxHigh.y, instance.bBoxHigh.z],
            };
        }
        elProps.placement = {
            origin,
            angles: core_geometry_1.YawPitchRollAngles.createDegrees(instance.yaw ?? 0, instance.pitch ?? 0, instance.roll ?? 0).toJSON(),
            bbox
        };
        if (instance.geometryStream) {
            elProps.geom = props.iModel[Symbols_1._nativeDb].convertOrUpdateGeometrySource({
                is2d: false,
                geom: instance.geometryStream,
                placement: elProps.placement,
                categoryId: elProps.category
            }, "GeometryStreamProps", props.options?.element ?? {}).geom;
        }
        if (instance.typeDefinition) {
            elProps.typeDefinition = instance.typeDefinition;
        }
        return elProps;
    }
    /**
     * GeometricElement3d serializes 'category', 'geometryStream', 'origin', 'yaw', 'pitch', 'roll',
     * 'bBoxLow', 'bBoxHigh', and 'typeDefinition'.
     * @inheritdoc
     * @beta
     */
    static serialize(props, iModel) {
        const inst = super.serialize(props, iModel);
        inst.category = { id: props.category };
        const assignPlacement = (placement) => {
            if (Array.isArray(placement.origin)) {
                inst.origin = { x: placement.origin[0], y: placement.origin[1], z: placement.origin[2] };
            }
            else {
                inst.origin = placement.origin;
            }
            inst.yaw = placement.angles.yaw;
            inst.pitch = placement.angles.pitch;
            inst.roll = placement.angles.roll;
            if (placement.bbox) {
                if (Array.isArray(placement.bbox.low)) {
                    inst.bBoxLow = { x: placement.bbox.low[0], y: placement.bbox.low[1], z: placement.bbox.low[2] };
                }
                else {
                    inst.bBoxLow = placement.bbox.low;
                }
                if (Array.isArray(placement.bbox.high)) {
                    inst.bBoxHigh = { x: placement.bbox.high[0], y: placement.bbox.high[1], z: placement.bbox.high[2] };
                }
                else {
                    inst.bBoxHigh = placement.bbox.high;
                }
            }
        };
        if (props.placement) {
            assignPlacement(props.placement);
        }
        if (props.elementGeometryBuilderParams) {
            const source = iModel[Symbols_1._nativeDb].convertOrUpdateGeometrySource({
                builder: props.elementGeometryBuilderParams,
                is2d: true,
                placement: props.placement,
                categoryId: props.category,
            }, "BinaryStream", {});
            inst.geometryStream = source.geom;
            if (source.placement) {
                assignPlacement(source.placement);
            }
        }
        if (props.geom) {
            const source = iModel[Symbols_1._nativeDb].convertOrUpdateGeometrySource({
                geom: props.geom,
                is2d: false,
                placement: props.placement,
                categoryId: props.category,
            }, "BinaryStream", {});
            inst.geometryStream = source.geom;
            if (source.placement) {
                assignPlacement(source.placement);
            }
        }
        inst.typeDefinition = props.typeDefinition;
        return inst;
    }
}
exports.GeometricElement3d = GeometricElement3d;
/** A 3d Graphical Element
 * @public @preview
 */
class GraphicalElement3d extends GeometricElement3d {
    static get className() { return "GraphicalElement3d"; }
    constructor(props, iModel) { super(props, iModel); }
}
exports.GraphicalElement3d = GraphicalElement3d;
/** An abstract base class to model information entities that intrinsically have 2d geometry.
 * @public @preview
 */
class GeometricElement2d extends GeometricElement {
    static get className() { return "GeometricElement2d"; }
    placement;
    typeDefinition;
    constructor(props, iModel) {
        super(props, iModel);
        this.placement = core_common_1.Placement2d.fromJSON(props.placement);
        if (props.typeDefinition)
            this.typeDefinition = core_common_1.TypeDefinition.fromJSON(props.typeDefinition);
    }
    toJSON() {
        const val = super.toJSON();
        val.placement = this.placement;
        if (undefined !== this.typeDefinition)
            val.typeDefinition = this.typeDefinition;
        return val;
    }
    /**
     * GeometricElement2d custom HandledProps includes 'category', 'geometryStream', 'origin', 'rotation',
     * 'bBoxLow', 'bBoxHigh', and 'typeDefinition'.
     * @inheritdoc
     * @beta
     */
    static _customHandledProps = [
        { propertyName: "category", source: "Class" },
        { propertyName: "geometryStream", source: "Class" },
        { propertyName: "origin", source: "Class" },
        { propertyName: "rotation", source: "Class" },
        { propertyName: "bBoxLow", source: "Class" },
        { propertyName: "bBoxHigh", source: "Class" },
        { propertyName: "typeDefinition", source: "Class" }
    ];
    /**
     * GeometricElement2d deserialize 'category', 'geometryStream', 'origin', 'rotation',
     * 'bBoxLow', 'bBoxHigh', and 'typeDefinition'.
     * @inheritdoc
     * @beta
     */
    static deserialize(props) {
        const elProps = super.deserialize(props);
        const instance = props.row;
        elProps.category = instance.category.id;
        const origin = instance.origin ? [instance.origin.x, instance.origin.y] : [0, 0];
        let bbox;
        if ("bBoxHigh" in instance && instance.bBoxHigh !== undefined && "bBoxLow" in instance && instance.bBoxLow !== undefined) {
            bbox = {
                low: [instance.bBoxLow.x, instance.bBoxLow.y],
                high: [instance.bBoxHigh.x, instance.bBoxHigh.y],
            };
        }
        elProps.placement = {
            origin,
            angle: instance.rotation,
            bbox,
        };
        if (instance.geometryStream) {
            const source = props.iModel[Symbols_1._nativeDb].convertOrUpdateGeometrySource({
                is2d: true,
                geom: instance.geometryStream,
                placement: elProps.placement,
                categoryId: elProps.category
            }, "GeometryStreamProps", props.options?.element ?? {});
            elProps.geom = source.geom;
            if (source.placement) {
                elProps.placement = source.placement;
            }
        }
        if (instance.typeDefinition) {
            elProps.typeDefinition = instance.typeDefinition;
        }
        return elProps;
    }
    /**
     * GeometricElement2d serializes 'category', 'geometryStream', 'origin', 'rotation',
     * 'bBoxLow', 'bBoxHigh', and 'typeDefinition'.
     * @inheritdoc
     * @beta
     */
    static serialize(props, iModel) {
        const inst = super.serialize(props, iModel);
        inst.category = { id: props.category };
        const assignPlacement = (placement) => {
            if (Array.isArray(placement.origin)) {
                inst.origin = { x: placement.origin[0], y: placement.origin[1] };
            }
            else {
                inst.origin = placement.origin;
            }
            inst.rotation = placement.angle;
            if (placement.bbox) {
                if (Array.isArray(placement.bbox.low)) {
                    inst.bBoxLow = { x: placement.bbox.low[0], y: placement.bbox.low[1] };
                }
                else {
                    inst.bBoxLow = placement.bbox.low;
                }
                if (Array.isArray(placement.bbox.high)) {
                    inst.bBoxHigh = { x: placement.bbox.high[0], y: placement.bbox.high[1] };
                }
                else {
                    inst.bBoxHigh = placement.bbox.high;
                }
            }
        };
        if (props.placement) {
            assignPlacement(props.placement);
        }
        if (props.elementGeometryBuilderParams) {
            const source = iModel[Symbols_1._nativeDb].convertOrUpdateGeometrySource({
                builder: props.elementGeometryBuilderParams,
                is2d: true,
                placement: props.placement,
                categoryId: props.category,
            }, "BinaryStream", {});
            inst.geometryStream = source.geom;
            if (source.placement) {
                assignPlacement(source.placement);
            }
        }
        if (props.geom) {
            const source = iModel[Symbols_1._nativeDb].convertOrUpdateGeometrySource({
                geom: props.geom,
                is2d: true,
                placement: props.placement,
                categoryId: props.category,
            }, "BinaryStream", {});
            inst.geometryStream = source.geom;
            if (source.placement) {
                assignPlacement(source.placement);
            }
        }
        inst.typeDefinition = props.typeDefinition;
        return inst;
    }
    collectReferenceIds(referenceIds) {
        super.collectReferenceIds(referenceIds);
        if (undefined !== this.typeDefinition)
            referenceIds.addElement(this.typeDefinition.id);
    }
}
exports.GeometricElement2d = GeometricElement2d;
/** An abstract base class for 2d Geometric Elements that are used to convey information within graphical presentations (like drawings).
 * @public @preview
 */
class GraphicalElement2d extends GeometricElement2d {
    static get className() { return "GraphicalElement2d"; }
    constructor(props, iModel) { super(props, iModel); }
}
exports.GraphicalElement2d = GraphicalElement2d;
/** 2d element used to annotate drawings and sheets.
 * @public @preview
 */
class AnnotationElement2d extends GraphicalElement2d {
    static get className() { return "AnnotationElement2d"; }
    constructor(props, iModel) { super(props, iModel); }
}
exports.AnnotationElement2d = AnnotationElement2d;
/** 2d element used to persist graphics for use in drawings.
 * @public @preview
 */
class DrawingGraphic extends GraphicalElement2d {
    static get className() { return "DrawingGraphic"; }
    constructor(props, iModel) { super(props, iModel); }
}
exports.DrawingGraphic = DrawingGraphic;
/** An Element that occupies real world space. Its coordinates are in the project space of its iModel.
 * @public @preview
 */
class SpatialElement extends GeometricElement3d {
    static get className() { return "SpatialElement"; }
    constructor(props, iModel) { super(props, iModel); }
}
exports.SpatialElement = SpatialElement;
/** An Element that is spatially located, has mass, and can be *touched*.
 * @public @preview
 */
class PhysicalElement extends SpatialElement {
    static get className() { return "PhysicalElement"; }
    /** If defined, the [[PhysicalMaterial]] that makes up this PhysicalElement. */
    physicalMaterial;
    constructor(props, iModel) {
        super(props, iModel);
        this.physicalMaterial = core_common_1.RelatedElement.fromJSON(props.physicalMaterial);
    }
    toJSON() {
        const val = super.toJSON();
        val.physicalMaterial = this.physicalMaterial?.toJSON();
        return val;
    }
}
exports.PhysicalElement = PhysicalElement;
/** Identifies a *tracked* real world location but has no mass and cannot be *touched*.
 * @public @preview
 */
class SpatialLocationElement extends SpatialElement {
    static get className() { return "SpatialLocationElement"; }
    constructor(props, iModel) { super(props, iModel); }
}
exports.SpatialLocationElement = SpatialLocationElement;
/** A Volume Element is a Spatial Location Element that is restricted to defining a volume.
 * @public @preview
 */
class VolumeElement extends SpatialLocationElement {
    static get className() { return "VolumeElement"; }
    constructor(props, iModel) { super(props, iModel); }
}
exports.VolumeElement = VolumeElement;
/** A SectionDrawingLocation element identifies the location of a [[SectionDrawing]] in the context of a [[SpatialModel]],
 * enabling [HyperModeling]($hypermodeling).
 * @note The associated ECClass was added to the BisCore schema in version 1.0.11.
 * @public @preview
 */
class SectionDrawingLocation extends SpatialLocationElement {
    /** The Id of the [[ViewDefinition]] to which this location refers. */
    sectionView;
    static get className() { return "SectionDrawingLocation"; }
    constructor(props, iModel) {
        super(props, iModel);
        this.sectionView = core_common_1.RelatedElement.fromJSON(props.sectionView) ?? core_common_1.RelatedElement.none;
    }
    toJSON() {
        return {
            ...super.toJSON(),
            sectionView: this.sectionView.toJSON(),
        };
    }
}
exports.SectionDrawingLocation = SectionDrawingLocation;
/** Information Content Element is an abstract base class for modeling pure information entities. Only the
 * core framework should directly subclass from Information Content Element. Domain and application developers
 * should start with the most appropriate subclass of Information Content Element.
 * @public @preview
 */
class InformationContentElement extends Element {
    static get className() { return "InformationContentElement"; }
    constructor(props, iModel) { super(props, iModel); }
}
exports.InformationContentElement = InformationContentElement;
/** Element used in conjunction with bis:ElementDrivesElement relationships to bundle multiple inputs before
 * driving the output element.
 * @beta
 */
class DriverBundleElement extends InformationContentElement {
    static get className() { return "DriverBundleElement"; }
    constructor(props, iModel) { super(props, iModel); }
}
exports.DriverBundleElement = DriverBundleElement;
/** Information Reference is an abstract base class for modeling entities whose main purpose is to reference something else.
 * @public @preview
 */
class InformationReferenceElement extends InformationContentElement {
    static get className() { return "InformationReferenceElement"; }
    constructor(props, iModel) { super(props, iModel); }
}
exports.InformationReferenceElement = InformationReferenceElement;
/** A Subject is an information element that describes what this repository (or part thereof) is about.
 * @public @preview
 */
class Subject extends InformationReferenceElement {
    static get className() { return "Subject"; }
    description;
    constructor(props, iModel) {
        super(props, iModel);
        this.description = props.description;
    }
    toJSON() {
        return super.toJSON(); // Entity.toJSON takes care of auto-handled properties
    }
    /** Create a Code for a Subject given a name that is meant to be unique within the scope of its parent Subject.
     * @param iModelDb The IModelDb
     * @param parentSubjectId The Id of the parent Subject that provides the scope for names of its child Subjects.
     * @param codeValue The child Subject name
     */
    static createCode(iModelDb, parentSubjectId, codeValue) {
        const codeSpec = iModelDb.codeSpecs.getByName(core_common_1.BisCodeSpec.subject);
        return new core_common_1.Code({ spec: codeSpec.id, scope: parentSubjectId, value: codeValue });
    }
    /** Create a Subject
     * @param iModelDb The IModelDb
     * @param parentSubjectId The new Subject will be a child of this Subject
     * @param name The name (codeValue) of the Subject
     * @param description The optional description of the Subject
     * @returns The newly constructed Subject
     * @throws [[IModelError]] if there is a problem creating the Subject
     */
    static create(iModelDb, parentSubjectId, name, description) {
        const subjectProps = {
            classFullName: this.classFullName,
            model: core_common_1.IModel.repositoryModelId,
            parent: new NavigationRelationship_1.SubjectOwnsSubjects(parentSubjectId),
            code: this.createCode(iModelDb, parentSubjectId, name),
            description,
        };
        return new Subject(subjectProps, iModelDb);
    }
    static insert(txnOrDb, parentSubjectId, name, description) {
        const txn = txnOrDb instanceof EditTxn_1.EditTxn ? txnOrDb : txnOrDb[Symbols_1._implicitTxn];
        const subject = this.create(txn.iModel, parentSubjectId, name, description);
        return subject.insert(txn);
    }
}
exports.Subject = Subject;
/** An InformationContentElement that identifies the content of a document.
 * The realized form of a document is called a DocumentCarrier (different class than Document).
 * For example, a will is a legal document. The will published into a PDF file is an ElectronicDocumentCopy.
 * The will printed onto paper is a PrintedDocumentCopy.
 * In this example, the Document only identifies, names, and tracks the content of the will.
 * @public @preview
 */
class Document extends InformationContentElement {
    static get className() { return "Document"; }
    constructor(props, iModel) { super(props, iModel); }
}
exports.Document = Document;
/** A document that represents a drawing, that is, a two-dimensional graphical representation of engineering data. A Drawing element is usually modelled by a [[DrawingModel]].
 * @public @preview
 */
class Drawing extends Document {
    _scaleFactor;
    /** A factor used by tools to adjust the size of text in [GeometricElement2d]($backend)s in the associated [DrawingModel]($backend) and to compute the
     * size of the [ViewAttachment]($backend) created when attaching the [Drawing]($backend) to a [Sheet]($backend).
     * Default: 1.
     * @note Attempting to set this property to a value less than or equal to zero will produce an exception.
     * @public @preview
     */
    get scaleFactor() { return this._scaleFactor; }
    set scaleFactor(factor) {
        if (factor <= 0) {
            if (this._scaleFactor === undefined) {
                // Entity constructor calls our setter before our constructor runs...don't throw an exception at that time,
                // because somebody may have persisted the value as zero.
                return;
            }
            throw new Error("Drawing.scaleFactor must be greater than zero");
        }
        this._scaleFactor = factor;
    }
    static get className() { return "Drawing"; }
    constructor(props, iModel) {
        super(props, iModel);
        this._scaleFactor = typeof props.scaleFactor === "number" && props.scaleFactor > 0 ? props.scaleFactor : 1;
    }
    toJSON() {
        const drawingProps = super.toJSON();
        // Entity.toJSON auto-magically sets drawingProps.scaleFactor from this.scaleFactor - unset if default value of 1.
        if (drawingProps.scaleFactor === 1) {
            delete drawingProps.scaleFactor;
        }
        return drawingProps;
    }
    /** The name of the DrawingModel class modeled by this element type. */
    static get drawingModelFullClassName() { return Model_1.DrawingModel.classFullName; }
    /** Create a Code for a Drawing given a name that is meant to be unique within the scope of the specified DocumentListModel.
     * @param iModel  The IModelDb
     * @param scopeModelId The Id of the DocumentListModel that contains the Drawing and provides the scope for its name.
     * @param codeValue The Drawing name
     */
    static createCode(iModel, scopeModelId, codeValue) {
        const codeSpec = iModel.codeSpecs.getByName(core_common_1.BisCodeSpec.drawing);
        return new core_common_1.Code({ spec: codeSpec.id, scope: scopeModelId, value: codeValue });
    }
    static insert(txnOrDb, documentListModelId, name, scaleFactor) {
        const txn = txnOrDb instanceof EditTxn_1.EditTxn ? txnOrDb : txnOrDb[Symbols_1._implicitTxn];
        const drawingProps = {
            classFullName: this.classFullName,
            model: documentListModelId,
            code: this.createCode(txn.iModel, documentListModelId, name),
        };
        if (scaleFactor !== undefined) {
            if (scaleFactor <= 0) {
                throw new Error("Drawing.scaleFactor must be greater than zero");
            }
            drawingProps.scaleFactor = scaleFactor;
        }
        const drawingId = txn.insertElement(drawingProps);
        const model = txn.iModel.models.createModel({
            classFullName: this.drawingModelFullClassName,
            modeledElement: { id: drawingId },
        });
        return txn.insertModel(model.toJSON());
    }
}
exports.Drawing = Drawing;
/** A document that represents a section drawing, that is, a graphical documentation derived from a planar
 * section of a spatial view. A SectionDrawing element is modelled by a [[SectionDrawingModel]] or a [[GraphicalModel3d]].
 * A [[SectionDrawingLocation]] can associate the drawing with a spatial location, enabling [HyperModeling]($hypermodeling).
 * @public @preview
 */
class SectionDrawing extends Drawing {
    /** The type of section used to generate the drawing. */
    sectionType;
    /** The spatial view from which the section was generated. */
    spatialView;
    /** A transform from the section drawing model's coordinates to spatial coordinates. */
    drawingToSpatialTransform;
    /** If the section drawing is placed onto a [[Sheet]] via a [[ViewAttachment]], a transform from the sheet's coordinates to spatial coordinates. */
    sheetToSpatialTransform;
    /** If the section drawing is placed onto a [[Sheet]] via a [[ViewAttachment]], the clip to apply to the sheet graphics when drawn in the context
     * of the spatial view.
     * @note The ClipVector is defined in spatial coordinates.
     */
    drawingBoundaryClip;
    /** If true, when displaying the section drawing as a [DrawingViewState]($frontend), the [[spatialView]] will also be displayed. */
    displaySpatialView;
    static get className() { return "SectionDrawing"; }
    static get drawingModelFullClassName() { return Model_1.SectionDrawingModel.classFullName; }
    constructor(props, iModel) {
        super(props, iModel);
        this.sectionType = core_bentley_1.JsonUtils.asInt(props.sectionType, core_common_1.SectionType.Section);
        this.spatialView = core_common_1.RelatedElement.fromJSON(props.spatialView) ?? core_common_1.RelatedElement.none;
        this.displaySpatialView = core_bentley_1.JsonUtils.asBool(props.jsonProperties?.displaySpatialView);
        const json = props.jsonProperties;
        if (!json)
            return;
        if (json.drawingToSpatialTransform)
            this.drawingToSpatialTransform = core_geometry_1.Transform.fromJSON(json.drawingToSpatialTransform);
        if (json.sheetToSpatialTransform)
            this.sheetToSpatialTransform = core_geometry_1.Transform.fromJSON(json.sheetToSpatialTransform);
        if (json.drawingBoundaryClip)
            this.drawingBoundaryClip = core_geometry_1.ClipVector.fromJSON(json.drawingBoundaryClip);
    }
    toJSON() {
        const props = {
            ...super.toJSON(),
            sectionType: this.sectionType,
            spatialView: this.spatialView.toJSON(),
        };
        if (!props.jsonProperties)
            props.jsonProperties = {};
        props.jsonProperties.displaySpatialView = this.displaySpatialView ? true : undefined;
        props.jsonProperties.drawingToSpatialTransform = this.drawingToSpatialTransform?.toJSON();
        props.jsonProperties.sheetToSpatialTransform = this.sheetToSpatialTransform?.toJSON();
        props.jsonProperties.drawingBoundaryClip = this.drawingBoundaryClip?.toJSON();
        return props;
    }
}
exports.SectionDrawing = SectionDrawing;
/** The template for a SheetBorder
 * @public @preview
 */
class SheetBorderTemplate extends Document {
    static get className() { return "SheetBorderTemplate"; }
    height;
    width;
    constructor(props, iModel) {
        super(props, iModel);
        this.height = props.height;
        this.width = props.width;
    }
}
exports.SheetBorderTemplate = SheetBorderTemplate;
/** The template for a [[Sheet]]
 * @public @preview
 */
class SheetTemplate extends Document {
    static get className() { return "SheetTemplate"; }
    height;
    width;
    border;
    constructor(props, iModel) {
        super(props, iModel);
        this.height = props.height;
        this.width = props.width;
        this.border = props.border;
    }
    collectReferenceIds(referenceIds) {
        super.collectReferenceIds(referenceIds);
        if (undefined !== this.border)
            referenceIds.addElement(this.border);
    }
}
exports.SheetTemplate = SheetTemplate;
/** A digital representation of a *sheet of paper*. Modeled by a [[SheetModel]].
 * @public @preview
 */
class Sheet extends Document {
    static get className() { return "Sheet"; }
    height;
    width;
    scale;
    sheetTemplate;
    constructor(props, iModel) {
        super(props, iModel);
        this.height = core_bentley_1.JsonUtils.asDouble(props.height);
        this.width = core_bentley_1.JsonUtils.asDouble(props.width);
        this.scale = props.scale;
        this.sheetTemplate = props.sheetTemplate ? core_bentley_1.Id64.fromJSON(props.sheetTemplate) : undefined;
    }
    collectReferenceIds(referenceIds) {
        super.collectReferenceIds(referenceIds);
        if (undefined !== this.sheetTemplate)
            referenceIds.addElement(this.sheetTemplate);
    }
    /** Create a Code for a Sheet given a name that is meant to be unique within the scope of the specified DocumentListModel.
     * @param iModel  The IModelDb
     * @param scopeModelId The Id of the DocumentListModel that contains the Sheet and provides the scope for its name.
     * @param codeValue The Sheet name
     */
    static createCode(iModel, scopeModelId, codeValue) {
        const codeSpec = iModel.codeSpecs.getByName(core_common_1.BisCodeSpec.sheet);
        return new core_common_1.Code({ spec: codeSpec.id, scope: scopeModelId, value: codeValue });
    }
}
exports.Sheet = Sheet;
/** Information Record Element is an abstract base class for modeling information records. Information Record
 * Element is the default choice if no other subclass of Information Content Element makes sense.
 * @public @preview
 */
class InformationRecordElement extends InformationContentElement {
    static get className() { return "InformationRecordElement"; }
    constructor(props, iModel) { super(props, iModel); }
}
exports.InformationRecordElement = InformationRecordElement;
/** A Definition Element holds configuration-related information that is meant to be referenced / shared.
 * @public @preview
 */
class DefinitionElement extends InformationContentElement {
    static get className() { return "DefinitionElement"; }
    /** If true, don't show this DefinitionElement in user interface lists. */
    isPrivate;
    constructor(props, iModel) {
        super(props, iModel);
        this.isPrivate = true === props.isPrivate;
    }
    /**
     * DefinitionElement custom HandledProps includes 'isPrivate'.
     * @inheritdoc
     * @beta
     */
    static _customHandledProps = [
        { propertyName: "isPrivate", source: "Class" },
    ];
    /**
     * DefinitionElement deserializes 'isPrivate'.
     * @inheritdoc
     * @beta
     */
    static deserialize(props) {
        const elProps = super.deserialize(props);
        if (props.row.isPrivate !== undefined)
            elProps.isPrivate = props.row.isPrivate;
        return elProps;
    }
    /**
     * DefinitionElement serialize 'isPrivate'.
     * @inheritdoc
     * @beta
     */
    static serialize(props, iModel) {
        const inst = super.serialize(props, iModel);
        if (undefined !== props.isPrivate) {
            inst.isPrivate = props.isPrivate;
        }
        return inst;
    }
    toJSON() {
        const val = super.toJSON();
        val.isPrivate = this.isPrivate;
        return val;
    }
}
exports.DefinitionElement = DefinitionElement;
/** This abstract class unifies DefinitionGroup and DefinitionContainer for relationship endpoint purposes.
 * @note The associated ECClass was added to the BisCore schema in version 1.0.10
 * @public @preview
 */
class DefinitionSet extends DefinitionElement {
    static get className() { return "DefinitionSet"; }
}
exports.DefinitionSet = DefinitionSet;
/** A DefinitionContainer exclusively owns a set of DefinitionElements contained within its sub-model (of type DefinitionModel).
 * @note The associated ECClass was added to the BisCore schema in version 1.0.10
 * @public @preview
 */
class DefinitionContainer extends DefinitionSet {
    static get className() { return "DefinitionContainer"; }
    /** Create a DefinitionContainer
     * @param iModelDb The IModelDb
     * @param definitionModelId The Id of the [DefinitionModel]($backend) that will contain this DefinitionContainer element.
     * @param code The Code for this DefinitionContainer.
     * @param isPrivate The optional hint, that if `true` means it should not be displayed in the UI.
     * @returns The newly constructed DefinitionContainer
     * @note There is not a predefined CodeSpec for DefinitionContainer elements, so it is the responsibility of the domain or application to create one.
     * @throws [[IModelError]] if there is a problem creating the DefinitionContainer
     */
    static create(iModelDb, definitionModelId, code, isPrivate) {
        const elementProps = {
            classFullName: this.classFullName,
            model: definitionModelId,
            code,
            isPrivate,
        };
        return new DefinitionContainer(elementProps, iModelDb);
    }
    static insert(txnOrDb, definitionModelId, code, isPrivate) {
        const txn = txnOrDb instanceof EditTxn_1.EditTxn ? txnOrDb : txnOrDb[Symbols_1._implicitTxn];
        const containerElement = this.create(txn.iModel, definitionModelId, code, isPrivate);
        const containerElementId = containerElement.insert(txn);
        const containerSubModelProps = {
            classFullName: Model_1.DefinitionModel.classFullName,
            modeledElement: { id: containerElementId },
            isPrivate,
        };
        txn.insertModel(containerSubModelProps);
        return containerElementId;
    }
}
exports.DefinitionContainer = DefinitionContainer;
/** A non-exclusive set of DefinitionElements grouped using the DefinitionGroupGroupsDefinitions relationship.
 * @note The associated ECClass was added to the BisCore schema in version 1.0.10
 * @public @preview
 */
class DefinitionGroup extends DefinitionSet {
    static get className() { return "DefinitionGroup"; }
    /** Create a DefinitionGroup
     * @param iModelDb The IModelDb
     * @param definitionModelId The Id of the [DefinitionModel]($backend) that will contain this DefinitionGroup element.
     * @param code The Code for this DefinitionGroup
     * @param isPrivate The optional hint, that if `true` means it should not be displayed in the UI.
     * @returns The newly constructed DefinitionGroup
     * @note There is not a predefined CodeSpec for DefinitionGroup elements, so it is the responsibility of the domain or application to create one.
     * @throws [[IModelError]] if there is a problem creating the DefinitionGroup
     */
    static create(iModelDb, definitionModelId, code, isPrivate) {
        const elementProps = {
            classFullName: this.classFullName,
            model: definitionModelId,
            code,
            isPrivate,
        };
        return new DefinitionGroup(elementProps, iModelDb);
    }
}
exports.DefinitionGroup = DefinitionGroup;
/** Defines a set of properties (the *type*) that may be associated with an element.
 * @public @preview
 */
class TypeDefinitionElement extends DefinitionElement {
    static get className() { return "TypeDefinitionElement"; }
    recipe;
    constructor(props, iModel) {
        super(props, iModel);
        this.recipe = core_common_1.RelatedElement.fromJSON(props.recipe);
    }
    collectReferenceIds(referenceIds) {
        super.collectReferenceIds(referenceIds);
        if (undefined !== this.recipe)
            referenceIds.addElement(this.recipe.id);
    }
}
exports.TypeDefinitionElement = TypeDefinitionElement;
/** Defines a recipe for generating instances from a definition.
 * @beta
 */
class RecipeDefinitionElement extends DefinitionElement {
    static get className() { return "RecipeDefinitionElement"; }
    constructor(props, iModel) { super(props, iModel); }
}
exports.RecipeDefinitionElement = RecipeDefinitionElement;
/** Defines a set of properties (the *type*) that can be associated with a Physical Element. A Physical
 * Type has a strong correlation with something that can be ordered from a catalog since all instances
 * share a common set of properties.
 * @public @preview
 */
class PhysicalType extends TypeDefinitionElement {
    static get className() { return "PhysicalType"; }
    /** If defined, the [[PhysicalMaterial]] that makes up this PhysicalType. */
    physicalMaterial;
    constructor(props, iModel) {
        super(props, iModel);
        this.physicalMaterial = core_common_1.RelatedElement.fromJSON(props.physicalMaterial);
    }
    toJSON() {
        const val = super.toJSON();
        val.physicalMaterial = this.physicalMaterial?.toJSON();
        return val;
    }
    /** Create a Code for a PhysicalType element given a name that is meant to be unique within the scope of the specified DefinitionModel.
     * @param iModel  The IModelDb
     * @param scopeModelId The Id of the DefinitionModel that contains the PhysicalType element and provides the scope for its name.
     * @param codeValue The PhysicalType name
     */
    static createCode(iModel, scopeModelId, codeValue) {
        const codeSpec = iModel.codeSpecs.getByName(core_common_1.BisCodeSpec.physicalType);
        return new core_common_1.Code({ spec: codeSpec.id, scope: scopeModelId, value: codeValue });
    }
}
exports.PhysicalType = PhysicalType;
/** Defines a set of properties (the *type*) that can be associated with a spatial location.
 * @public @preview
 */
class SpatialLocationType extends TypeDefinitionElement {
    static get className() { return "SpatialLocationType"; }
    constructor(props, iModel) { super(props, iModel); }
    /** Create a Code for a SpatialLocationType element given a name that is meant to be unique within the scope of the specified DefinitionModel.
     * @param iModel  The IModelDb
     * @param scopeModelId The Id of the DefinitionModel that contains the SpatialLocationType element and provides the scope for its name.
     * @param codeValue The SpatialLocationType name
     */
    static createCode(iModel, scopeModelId, codeValue) {
        const codeSpec = iModel.codeSpecs.getByName(core_common_1.BisCodeSpec.spatialLocationType);
        return new core_common_1.Code({ spec: codeSpec.id, scope: scopeModelId, value: codeValue });
    }
}
exports.SpatialLocationType = SpatialLocationType;
/** A TemplateRecipe3d is a DefinitionElement that has a sub-model that contains the 3d template elements.
 * @beta
 */
class TemplateRecipe3d extends RecipeDefinitionElement {
    static get className() { return "TemplateRecipe3d"; }
    constructor(props, iModel) { super(props, iModel); }
    /** Create a Code for a TemplateRecipe3d given a name that is meant to be unique within the scope of its Model.
     * @param iModelDb The IModelDb
     * @param definitionModelId The Id of the [DefinitionModel]($backend) that contains this TemplateRecipe3d element.
     * @param codeValue The name of the TemplateRecipe3d element.
     */
    static createCode(iModelDb, definitionModelId, codeValue) {
        const codeSpec = iModelDb.codeSpecs.getByName(core_common_1.BisCodeSpec.templateRecipe3d);
        return new core_common_1.Code({ spec: codeSpec.id, scope: definitionModelId, value: codeValue });
    }
    /** Create a TemplateRecipe3d
     * @param iModelDb The IModelDb
     * @param definitionModelId The Id of the [DefinitionModel]($backend) that contains this TemplateRecipe3d element.
     * @param name The name (Code.value) of the TemplateRecipe3d
     * @returns The newly constructed TemplateRecipe3d
     * @throws [[IModelError]] if there is a problem creating the TemplateRecipe3d
     */
    static create(iModelDb, definitionModelId, name, isPrivate) {
        const elementProps = {
            classFullName: this.classFullName,
            model: definitionModelId,
            code: this.createCode(iModelDb, definitionModelId, name),
            isPrivate,
        };
        return new TemplateRecipe3d(elementProps, iModelDb);
    }
    static insert(txnOrDb, definitionModelId, name, isPrivate) {
        const txn = txnOrDb instanceof EditTxn_1.EditTxn ? txnOrDb : txnOrDb[Symbols_1._implicitTxn];
        const element = this.create(txn.iModel, definitionModelId, name, isPrivate);
        const modeledElementId = element.insert(txn);
        const modelProps = {
            classFullName: Model_1.PhysicalModel.classFullName,
            modeledElement: { id: modeledElementId },
            isTemplate: true,
        };
        return txn.insertModel(modelProps); // will be the same value as modeledElementId
    }
}
exports.TemplateRecipe3d = TemplateRecipe3d;
/** Defines a set of properties (the *type*) that can be associated with a 2D Graphical Element.
 * @public @preview
 */
class GraphicalType2d extends TypeDefinitionElement {
    static get className() { return "GraphicalType2d"; }
    constructor(props, iModel) { super(props, iModel); }
    /** Create a Code for a GraphicalType2d element given a name that is meant to be unique within the scope of the specified DefinitionModel.
     * @param iModel  The IModelDb
     * @param scopeModelId The Id of the DefinitionModel that contains the GraphicalType2d element and provides the scope for its name.
     * @param codeValue The GraphicalType2d name
     */
    static createCode(iModel, scopeModelId, codeValue) {
        const codeSpec = iModel.codeSpecs.getByName(core_common_1.BisCodeSpec.graphicalType2d);
        return new core_common_1.Code({ spec: codeSpec.id, scope: scopeModelId, value: codeValue });
    }
}
exports.GraphicalType2d = GraphicalType2d;
/** A recipe that uses a 2D template for creating new instances.
 * @beta
 */
class TemplateRecipe2d extends RecipeDefinitionElement {
    static get className() { return "TemplateRecipe2d"; }
    constructor(props, iModel) { super(props, iModel); }
    /** Create a Code for a TemplateRecipe2d given a name that is meant to be unique within the scope of its Model.
     * @param iModelDb The IModelDb
     * @param definitionModelId The Id of the [DefinitionModel]($backend) that contains this TemplateRecipe2d element.
     * @param codeValue The name of the TemplateRecipe2d element.
     */
    static createCode(iModelDb, definitionModelId, codeValue) {
        const codeSpec = iModelDb.codeSpecs.getByName(core_common_1.BisCodeSpec.templateRecipe2d);
        return new core_common_1.Code({ spec: codeSpec.id, scope: definitionModelId, value: codeValue });
    }
    /** Create a TemplateRecipe2d
     * @param iModelDb The IModelDb
     * @param definitionModelId The Id of the [DefinitionModel]($backend) that contains this TemplateRecipe2d element.
     * @param name The name (Code.value) of the TemplateRecipe2d
     * @returns The newly constructed TemplateRecipe2d
     * @throws [[IModelError]] if there is a problem creating the TemplateRecipe2d
     */
    static create(iModelDb, definitionModelId, name, isPrivate) {
        const elementProps = {
            classFullName: this.classFullName,
            model: definitionModelId,
            code: this.createCode(iModelDb, definitionModelId, name),
            isPrivate,
        };
        return new TemplateRecipe2d(elementProps, iModelDb);
    }
    static insert(txnOrDb, definitionModelId, name, isPrivate) {
        const txn = txnOrDb instanceof EditTxn_1.EditTxn ? txnOrDb : txnOrDb[Symbols_1._implicitTxn];
        const element = this.create(txn.iModel, definitionModelId, name, isPrivate);
        const modeledElementId = element.insert(txn);
        const modelProps = {
            classFullName: Model_1.DrawingModel.classFullName,
            modeledElement: { id: modeledElementId },
            isTemplate: true,
        };
        return txn.insertModel(modelProps); // will be the same value as modeledElementId
    }
}
exports.TemplateRecipe2d = TemplateRecipe2d;
/** An abstract base class for elements that establishes a particular modeling perspective for its parent Subject.
 * Instances are always sub-modeled by a specialization of Model of the appropriate modeling perspective.
 * @see [iModel Information Hierarchy]($docs/bis/guide/data-organization/top-of-the-world), [[Subject]], [[Model]]
 * @public @preview
 */
class InformationPartitionElement extends InformationContentElement {
    static get className() { return "InformationPartitionElement"; }
    /** A human-readable string describing the intent of the partition. */
    description;
    constructor(props, iModel) {
        super(props, iModel);
        this.description = props.description;
    }
    toJSON() {
        return super.toJSON(); // Entity.toJSON takes care of auto-handled properties
    }
    /** Create a code that can be used for any subclass of InformationPartitionElement.
     * @param iModelDb The IModelDb
     * @param parentSubjectId The Id of the parent Subject that provides the scope for names of its child InformationPartitionElements.
     * @param codeValue The InformationPartitionElement name
     */
    static createCode(iModel, parentSubjectId, codeValue) {
        const codeSpec = iModel.codeSpecs.getByName(core_common_1.BisCodeSpec.informationPartitionElement);
        return new core_common_1.Code({ spec: codeSpec.id, scope: parentSubjectId, value: codeValue });
    }
}
exports.InformationPartitionElement = InformationPartitionElement;
/** A DefinitionPartition element establishes a *Definition* modeling perspective for its parent Subject.
 * A DefinitionPartition is always sub-modeled by a DefinitionModel.
 * @see [[DefinitionModel]]
 * @public @preview
 */
class DefinitionPartition extends InformationPartitionElement {
    static get className() { return "DefinitionPartition"; }
}
exports.DefinitionPartition = DefinitionPartition;
/** A DocumentPartition element establishes a *Document* modeling perspective for its parent Subject.
 * A DocumentPartition is always sub-modeled by a DocumentListModel.
 * @see [[DocumentListModel]]
 * @public @preview
 */
class DocumentPartition extends InformationPartitionElement {
    static get className() { return "DocumentPartition"; }
}
exports.DocumentPartition = DocumentPartition;
/** A GroupInformationPartition element establishes a *Group Information* modeling perspective for its parent Subject.
 * A GroupInformationPartition is always sub-modeled by a GroupInformationModel.
 * @see [[GroupInformationModel]]
 * @public @preview
 */
class GroupInformationPartition extends InformationPartitionElement {
    static get className() { return "GroupInformationPartition"; }
}
exports.GroupInformationPartition = GroupInformationPartition;
/** A GraphicalPartition3d element establishes a *3D Graphical* modeling perspective for its parent Subject.
 * A GraphicalPartition3d is always sub-modeled by a GraphicalModel3d.
 * @note The associated ECClass was added to the BisCore schema in version 1.0.8
 * @see [[GraphicalModel3d]]
 * @public @preview
 */
class GraphicalPartition3d extends InformationPartitionElement {
    static get className() { return "GraphicalPartition3d"; }
}
exports.GraphicalPartition3d = GraphicalPartition3d;
/** An InformationRecordPartition element establishes a *Information Record* modeling perspective for its parent Subject.
 * A InformationRecordPartition is always sub-modeled by an InformationRecordModel.
 * @see [[InformationRecordModel]]
 * @public @preview
 */
class InformationRecordPartition extends InformationPartitionElement {
    static get className() { return "InformationRecordPartition"; }
}
exports.InformationRecordPartition = InformationRecordPartition;
/** A LinkPartition element establishes a *Link* modeling perspective for its parent Subject. A LinkPartition is always sub-modeled by a LinkModel.
 * @see [[LinkModel]]
 * @public @preview
 */
class LinkPartition extends InformationPartitionElement {
    static get className() { return "LinkPartition"; }
}
exports.LinkPartition = LinkPartition;
/** A PhysicalPartition element establishes a *Physical* modeling perspective for its parent Subject. A PhysicalPartition is always sub-modeled by a PhysicalModel.
 * @see [[PhysicalModel]]
 * @public @preview
 */
class PhysicalPartition extends InformationPartitionElement {
    static get className() { return "PhysicalPartition"; }
}
exports.PhysicalPartition = PhysicalPartition;
/** A SpatialLocationPartition element establishes a *SpatialLocation* modeling perspective for its parent Subject.
 * A SpatialLocationPartition is always sub-modeled by a SpatialLocationModel.
 * @see [[SpatialLocationModel]]
 * @public @preview
 */
class SpatialLocationPartition extends InformationPartitionElement {
    static get className() { return "SpatialLocationPartition"; }
}
exports.SpatialLocationPartition = SpatialLocationPartition;
/** A SheetIndexPartition element establishes a [[SheetIndex]] modeling perspective for its parent [[Subject]].
 * A SheetIndexPartition is always sub-modeled by a [[SheetIndexModel]].
 * @beta
 */
class SheetIndexPartition extends InformationPartitionElement {
    static get className() { return "SheetIndexPartition"; }
}
exports.SheetIndexPartition = SheetIndexPartition;
/** Group Information is an abstract base class for modeling entities whose main purpose is to reference a group of related elements.
 * @public @preview
 */
class GroupInformationElement extends InformationReferenceElement {
    static get className() { return "GroupInformationElement"; }
}
exports.GroupInformationElement = GroupInformationElement;
/** An information element that specifies a link.
 * @public @preview
 */
class LinkElement extends InformationReferenceElement {
    static get className() { return "LinkElement"; }
    /** Create a Code for a LinkElement given a name that is meant to be unique within the scope of the specified Model.
     * @param iModel  The IModelDb
     * @param scopeModelId The Id of the Model that contains the LinkElement and provides the scope for its name.
     * @param codeValue The LinkElement name
     */
    static createCode(iModel, scopeModelId, codeValue) {
        const codeSpec = iModel.codeSpecs.getByName(core_common_1.BisCodeSpec.linkElement);
        return new core_common_1.Code({ spec: codeSpec.id, scope: scopeModelId, value: codeValue });
    }
}
exports.LinkElement = LinkElement;
/** An information element that specifies a URL link.
 * @public @preview
 */
class UrlLink extends LinkElement {
    static get className() { return "UrlLink"; }
    description;
    url;
    constructor(props, iModel) {
        super(props, iModel);
        this.description = props.description;
        this.url = props.url;
    }
    /**
     * UrlLink custom HandledProps includes 'description', and 'url'.
     * @inheritdoc
     * @beta
     */
    static _customHandledProps = [
        { propertyName: "description", source: "Class" },
        { propertyName: "url", source: "Class" },
    ];
    /**
     * UrlLink deserializes 'description', and 'url'.
     * @inheritdoc
     * @beta
     */
    static deserialize(props) {
        const elProps = super.deserialize(props);
        elProps.description = props.row.description ?? "";
        elProps.url = props.row.url;
        return elProps;
    }
    /**
     * UrlLink serializes 'description', and 'url'.
     * @inheritdoc
     * @beta
     */
    static serialize(props, iModel) {
        const inst = super.serialize(props, iModel);
        inst.description = props.description;
        return inst;
    }
    toJSON() {
        const val = super.toJSON();
        val.description = this.description;
        val.url = this.url;
        return val;
    }
}
exports.UrlLink = UrlLink;
/** Represents a folder-like structure that organizes repositories (typically files) in an external system.
 * @note The associated ECClass was added to the BisCore schema in version 1.0.13
 * @alpha
 */
class FolderLink extends UrlLink {
    static get className() { return "FolderLink"; }
}
exports.FolderLink = FolderLink;
/** An information element that links to a repository.
 * @public @preview
 */
class RepositoryLink extends UrlLink {
    static get className() { return "RepositoryLink"; }
    repositoryGuid;
    /** @note This property was added to the BisCore schema in version 1.0.13 */
    format;
    constructor(props, iModel) {
        super(props, iModel);
        this.repositoryGuid = props.repositoryGuid;
        this.format = props.format;
    }
    toJSON() {
        const val = super.toJSON();
        val.repositoryGuid = this.repositoryGuid;
        val.format = this.format;
        return val;
    }
}
exports.RepositoryLink = RepositoryLink;
/** An information element that links to an embedded file.
 * @public @preview
 */
class EmbeddedFileLink extends LinkElement {
    static get className() { return "EmbeddedFileLink"; }
}
exports.EmbeddedFileLink = EmbeddedFileLink;
/** A real world entity is modeled as a Role Element when a set of external circumstances define an important
 * role (one that is worth tracking) that is not intrinsic to the entity playing the role. For example,
 * a person can play the role of a teacher or a rock can play the role of a boundary marker.
 * @public @preview
 */
class RoleElement extends Element {
    static get className() { return "RoleElement"; }
}
exports.RoleElement = RoleElement;
/** A Definition Element that specifies a collection of geometry that is meant to be reused across Geometric
 * Element instances. Leveraging Geometry Parts can help reduce file size and improve display performance.
 * @public @preview
 */
class GeometryPart extends DefinitionElement {
    static get className() { return "GeometryPart"; }
    geom;
    bbox;
    constructor(props, iModel) {
        super(props, iModel);
        this.geom = props.geom;
        this.bbox = core_geometry_1.Range3d.fromJSON(props.bbox);
    }
    /**
     * GeometryPart custom HandledProps includes 'geometryStream', 'bBoxHigh', and 'bBoxLow'.
     * @inheritdoc
     * @beta
     */
    static _customHandledProps = [
        { propertyName: "geometryStream", source: "Class" },
        { propertyName: "bBoxLow", source: "Class" },
        { propertyName: "bBoxHigh", source: "Class" },
    ];
    /**
     * GeometryPart deserializes 'geometryStream', 'bBoxHigh', and 'bBoxLow'.
     * @inheritdoc
     * @beta
     */
    static deserialize(props) {
        const elProps = super.deserialize(props);
        const instance = props.row;
        if ("bBoxHigh" in instance && instance.bBoxHigh !== undefined && "bBoxLow" in instance && instance.bBoxLow !== undefined) {
            elProps.bbox = {
                low: [instance.bBoxLow.x, instance.bBoxLow.y, instance.bBoxLow.z],
                high: [instance.bBoxHigh.x, instance.bBoxHigh.y, instance.bBoxHigh.z],
            };
        }
        if (instance.geometryStream) {
            elProps.geom = props.iModel[Symbols_1._nativeDb].convertOrUpdateGeometryPart({
                geom: instance.geometryStream,
                is2d: false,
                bbox: elProps.bbox,
            }, "GeometryStreamProps", props.options?.element ?? {}).geom;
        }
        return elProps;
    }
    /**
     * GeometryPart serialize 'geometryStream', 'bBoxHigh', and 'bBoxLow'.
     * @inheritdoc
     * @beta
     */
    static serialize(props, iModel) {
        const inst = super.serialize(props, iModel);
        if (undefined !== props.geom) {
            const source = inst.geometryStream = iModel[Symbols_1._nativeDb].convertOrUpdateGeometryPart({
                geom: props.geom,
                is2d: false,
                bbox: props.bbox,
            }, "BinaryStream", {});
            inst.geometryStream = source.geom;
            if (source.bbox) {
                props.bbox = source.bbox;
            }
        }
        if (undefined !== props.bbox) {
            if (Array.isArray(props.bbox.low)) {
                inst.bBoxLow = { x: props.bbox.low[0], y: props.bbox.low[1], z: props.bbox.low[2] };
            }
            else {
                inst.bBoxLow = props.bbox.low;
            }
            if (Array.isArray(props.bbox.high)) {
                inst.bBoxHigh = { x: props.bbox.high[0], y: props.bbox.high[1], z: props.bbox.high[2] };
            }
            else {
                inst.bBoxHigh = props.bbox.high;
            }
        }
        return inst;
    }
    toJSON() {
        const val = super.toJSON();
        val.geom = this.geom;
        val.bbox = this.bbox;
        return val;
    }
    /** Create a Code for a GeometryPart element given a name that is meant to be unique within the scope of the specified DefinitionModel.
     * @param iModel  The IModelDb
     * @param scopeModelId The Id of the DefinitionModel that contains the GeometryPart element and provides the scope for its name.
     * @param codeValue The GeometryPart name
     * @note GeometryPart elements are not required to be named (have a non-empty Code).
     */
    static createCode(iModel, scopeModelId, codeValue) {
        const codeSpec = iModel.codeSpecs.getByName(core_common_1.BisCodeSpec.geometryPart);
        return new core_common_1.Code({ spec: codeSpec.id, scope: scopeModelId, value: codeValue });
    }
}
exports.GeometryPart = GeometryPart;
/** The definition element for a line style
 * @public @preview
 */
class LineStyle extends DefinitionElement {
    static get className() { return "LineStyle"; }
    description;
    data;
    constructor(props, iModel) {
        super(props, iModel);
        this.description = props.description;
        this.data = props.data;
    }
    /**
     * LineStyle custom HandledProps includes 'data'.
     * @inheritdoc
     * @beta
     */
    static _customHandledProps = [
        { propertyName: "data", source: "Class" },
    ];
    /**
     * LineStyle deserializes 'data'.
     * @inheritdoc
     * @beta
     */
    static deserialize(props) {
        const elProps = super.deserialize(props);
        const instance = props.row;
        elProps.data = instance.data ?? "";
        return elProps;
    }
    /**
     * LineStyle serializes 'data'.
     * @inheritdoc
     * @beta
     */
    static serialize(props, iModel) {
        const inst = super.serialize(props, iModel);
        inst.data = props.data;
        return inst;
    }
    /** Create a Code for a LineStyle definition given a name that is meant to be unique within the scope of the specified model.
     * @param iModel The IModel
     * @param scopeModelId The Id of the DefinitionModel that contains the LineStyle and provides the scope for its name.
     * @param codeValue The name of the LineStyle
     * @returns A LineStyle Code
     */
    static createCode(iModel, scopeModelId, codeValue) {
        return new core_common_1.Code({ spec: iModel.codeSpecs.getByName(core_common_1.BisCodeSpec.lineStyle).id, scope: scopeModelId, value: codeValue });
    }
}
exports.LineStyle = LineStyle;
/** Describes how to animate a view of a [[GeometricModel]] to show change over time using a [RenderSchedule.Script]($common).
 * @note This class was introduced in version 01.00.13 of the BisCore ECSchema. It should only be used with [[IModelDb]]s containing that version or newer.
 * @public @preview
 */
class RenderTimeline extends InformationRecordElement {
    static get className() { return "RenderTimeline"; }
    /** A human-readable description of the timeline, which may be an empty string. */
    description;
    /** The JSON representation of the instructions for visualizing change over time.
     * @see [RenderSchedule.Script]($common) for the API for working with the script.
     */
    scriptProps;
    constructor(props, iModel) {
        super(props, iModel);
        this.description = props.description ?? "";
        this.scriptProps = RenderTimeline.parseScriptProps(props.script);
    }
    static fromJSON(props, iModel) {
        return new RenderTimeline(props, iModel);
    }
    toJSON() {
        const props = super.toJSON();
        if (this.description.length > 0)
            props.description = this.description;
        props.script = JSON.stringify(this.scriptProps);
        return props;
    }
    /**
     * RenderTimeline deserialize checks if Schedule Script Element Ids need to be omitted, and if so, removes them.
     * @inheritdoc
     * @beta
     */
    static deserialize(props) {
        const elProps = super.deserialize(props);
        const options = props.options?.element?.renderTimeline;
        // Omit Schedule Script Element Ids if the option is set
        if (options?.omitScriptElementIds && elProps.script) {
            const scriptProps = RenderTimeline.parseScriptProps(elProps.script);
            elProps.script = JSON.stringify(core_common_1.RenderSchedule.Script.removeScheduleScriptElementIds(scriptProps));
        }
        return elProps;
    }
    static parseScriptProps(json) {
        try {
            return JSON.parse(json);
        }
        catch {
            return [];
        }
    }
    collectReferenceIds(ids) {
        super.collectReferenceIds(ids);
        const script = core_common_1.RenderSchedule.Script.fromJSON(this.scriptProps);
        script?.discloseIds(ids);
    }
    /** @alpha */
    static async onCloned(context, sourceProps, targetProps) {
        await super.onCloned(context, sourceProps, targetProps);
        if (context.isBetweenIModels)
            targetProps.script = JSON.stringify(this.remapScript(context, this.parseScriptProps(targetProps.script)));
    }
    /** Remap Ids when cloning a RenderSchedule.Script between iModels on a DisplayStyle or RenderTimeline.
     * @beta
     */
    static remapScript(context, input) {
        const scriptProps = [];
        if (!Array.isArray(input))
            return scriptProps;
        const elementIds = new core_bentley_1.OrderedId64Array();
        for (const model of input) {
            const modelId = context.findTargetElementId(model.modelId);
            if (!core_bentley_1.Id64.isValid(modelId))
                continue;
            model.modelId = modelId;
            scriptProps.push(model);
            for (const element of model.elementTimelines) {
                elementIds.clear();
                for (const sourceId of core_common_1.RenderSchedule.ElementTimeline.getElementIds(element.elementIds)) {
                    const targetId = context.findTargetElementId(sourceId);
                    if (core_bentley_1.Id64.isValid(targetId))
                        elementIds.insert(targetId);
                }
                element.elementIds = core_bentley_1.CompressedId64Set.compressIds(elementIds);
            }
        }
        return scriptProps;
    }
}
exports.RenderTimeline = RenderTimeline;
/** Captures project-level properties of the real-world entity represented by its parent [[Subject]].
 * @beta
 */
class ProjectInformationRecord extends InformationRecordElement {
    static get className() { return "ProjectInformationRecord"; }
    /** The properties of the project. */
    projectInformation;
    constructor(props, iModel) {
        super(props, iModel);
        this.projectInformation = {
            projectNumber: props.projectNumber,
            projectName: props.projectName,
            location: props.location,
        };
    }
    static onInsert(arg) {
        super.onInsert(arg);
        const parentId = arg.props.parent?.id;
        const subject = undefined !== parentId ? arg.iModel.elements.tryGetElement(parentId) : undefined;
        if (!(subject instanceof Subject)) {
            throw new Error("ProjectInformationRecord must be a child of a Subject");
        }
    }
    /** Create a new ProjectInformationRecord element ready to be inserted into the iModel.
     * @throws Error if the iModel contains a version of the BisCore schema older than 01.00.25.
     */
    static create(args) {
        args.iModel.requireMinimumSchemaVersion("BisCore", new ecschema_metadata_1.ECVersion(1, 0, 25), "ProjectInformationRecord");
        const parent = args.iModel.elements.getElement(args.parentSubjectId);
        const props = {
            classFullName: this.classFullName,
            model: parent.model,
            code: args.code ?? core_common_1.Code.createEmpty(),
            parent: new NavigationRelationship_1.SubjectOwnsProjectInformationRecord(args.parentSubjectId),
            projectName: args.projectName,
            projectNumber: args.projectNumber,
            location: args.location,
        };
        return new this(props, args.iModel);
    }
    toJSON() {
        const props = super.toJSON();
        for (const key of ["projectNumber", "projectName", "location"]) {
            const value = this.projectInformation[key];
            if (undefined !== value) {
                props[key] = value;
            }
        }
        return props;
    }
}
exports.ProjectInformationRecord = ProjectInformationRecord;
//# sourceMappingURL=Element.js.map