"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 ViewDefinitions
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.LightLocation = exports.ViewAttachment = exports.AuxCoordSystemSpatial = exports.AuxCoordSystem3d = exports.AuxCoordSystem2d = exports.AuxCoordSystem = exports.TemplateViewDefinition3d = exports.TemplateViewDefinition2d = exports.SheetViewDefinition = exports.DrawingViewDefinition = exports.ViewDefinition2d = exports.OrthographicViewDefinition = exports.SpatialViewDefinition = exports.ViewDefinition3d = exports.ViewDefinition = exports.CategorySelector = exports.ModelSelector = void 0;
const core_bentley_1 = require("@itwin/core-bentley");
const core_geometry_1 = require("@itwin/core-geometry");
const core_common_1 = require("@itwin/core-common");
const Element_1 = require("./Element");
/** Holds the list of Ids of GeometricModels displayed by a [[SpatialViewDefinition]]. Multiple SpatialViewDefinitions may point to the same ModelSelector.
 * @see [ModelSelectorState]($frontend)
 * @public @preview
 */
class ModelSelector extends Element_1.DefinitionElement {
    static get className() { return "ModelSelector"; }
    /** The array of modelIds of the GeometricModels displayed by this ModelSelector */
    models;
    constructor(props, iModel) {
        super(props, iModel);
        this.models = props.models;
    }
    toJSON() {
        const val = super.toJSON();
        val.models = this.models;
        return val;
    }
    /**
     * ModelSelector custom HandledProps includes 'models'.
     * @inheritdoc
     * @beta
     */
    static _customHandledProps = [
        { propertyName: "models", source: "Class" },
    ];
    /**
     * ModelSelector deserializes 'models'.
     * @inheritdoc
     * @beta
     */
    static deserialize(props) {
        const elProps = super.deserialize(props);
        const instance = props.row;
        // eslint-disable-next-line @typescript-eslint/no-deprecated
        elProps.models = props.iModel.withPreparedStatement("SELECT TargetECInstanceId FROM Bis.ModelSelectorRefersToModels WHERE SourceECInstanceId=?", (statement) => {
            statement.bindId(1, instance.id);
            const ids = [];
            while (core_bentley_1.DbResult.BE_SQLITE_ROW === statement.step()) {
                ids.push(statement.getValue(0).getId());
            }
            return ids;
        });
        return elProps;
    }
    collectReferenceIds(referenceIds) {
        super.collectReferenceIds(referenceIds);
        this.models.forEach((modelId) => referenceIds.addModel(modelId));
    }
    /** Create a Code for a ModelSelector 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 ModelSelector and provides the scope for its name.
     * @param codeValue The ModelSelector name
     */
    static createCode(iModel, scopeModelId, codeValue) {
        const codeSpec = iModel.codeSpecs.getByName(core_common_1.BisCodeSpec.modelSelector);
        return new core_common_1.Code({ spec: codeSpec.id, scope: scopeModelId, value: codeValue });
    }
    /**
     * Create a ModelSelector to select which Models are displayed by a ViewDefinition.
     * @param iModelDb The iModel
     * @param definitionModelId The [[DefinitionModel]]
     * @param name The name/CodeValue of the ModelSelector
     * @param models Array of models to select for display
     * @returns The newly constructed ModelSelector element.
     * @throws [[IModelError]] if unable to create the element.
     */
    static create(iModelDb, definitionModelId, name, models) {
        const modelSelectorProps = {
            classFullName: this.classFullName,
            code: this.createCode(iModelDb, definitionModelId, name),
            model: definitionModelId,
            models,
            isPrivate: false,
        };
        return new ModelSelector(modelSelectorProps, iModelDb);
    }
    /**
     * Insert a ModelSelector to select which Models are displayed by a ViewDefinition.
     * @param iModelDb Insert into this iModel
     * @param definitionModelId Insert the new ModelSelector into this DefinitionModel
     * @param name The name/CodeValue of the ModelSelector
     * @param models Array of models to select for display
     * @returns The Id of the newly inserted ModelSelector element.
     * @throws [[IModelError]] if unable to insert the element.
     */
    static insert(iModelDb, definitionModelId, name, models) {
        const modelSelector = this.create(iModelDb, definitionModelId, name, models);
        return iModelDb.elements.insertElement(modelSelector.toJSON());
    }
}
exports.ModelSelector = ModelSelector;
/** Holds a list of Ids of Categories to be displayed in a view.
 * @see [CategorySelectorState]($frontend)
 * See [how to create a CategorySelector]($docs/learning/backend/CreateElements.md#CategorySelector).
 * @public @preview
 */
class CategorySelector extends Element_1.DefinitionElement {
    static get className() { return "CategorySelector"; }
    /** The array of element Ids of the Categories selected by this CategorySelector */
    categories;
    constructor(props, iModel) {
        super(props, iModel);
        this.categories = props.categories;
    }
    toJSON() {
        const val = super.toJSON();
        val.categories = this.categories;
        return val;
    }
    /**
     * CategorySelector custom HandledProps includes 'categories'.
     * @inheritdoc
     * @beta
     */
    static _customHandledProps = [
        { propertyName: "categories", source: "Class" },
    ];
    /**
     * CategorySelector deserializes 'categories'.
     * @inheritdoc
     * @beta
     */
    static deserialize(props) {
        const elProps = super.deserialize(props);
        const instance = props.row;
        // eslint-disable-next-line @typescript-eslint/no-deprecated
        elProps.categories = props.iModel.withPreparedStatement("SELECT TargetECInstanceId FROM Bis.CategorySelectorRefersToCategories WHERE SourceECInstanceId=?", (statement) => {
            statement.bindId(1, instance.id);
            const ids = [];
            while (core_bentley_1.DbResult.BE_SQLITE_ROW === statement.step()) {
                ids.push(statement.getValue(0).getId());
            }
            return ids;
        });
        return elProps;
    }
    collectReferenceIds(referenceIds) {
        super.collectReferenceIds(referenceIds);
        this.categories.forEach((categoryId) => referenceIds.addElement(categoryId));
    }
    /** Create a Code for a CategorySelector 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 CategorySelector and provides the scope for its name.
     * @param codeValue The CategorySelector name
     */
    static createCode(iModel, scopeModelId, codeValue) {
        const codeSpec = iModel.codeSpecs.getByName(core_common_1.BisCodeSpec.categorySelector);
        return new core_common_1.Code({ spec: codeSpec.id, scope: scopeModelId, value: codeValue });
    }
    /**
     * Create a CategorySelector to select which categories are displayed by a ViewDefinition.
     * @param iModelDb The iModel
     * @param definitionModelId The [[DefinitionModel]]
     * @param name The name of the CategorySelector
     * @param categories Array of categories to select for display
     * @returns The newly constructed CategorySelector element.
     * @throws [[IModelError]] if unable to create the element.
     */
    static create(iModelDb, definitionModelId, name, categories) {
        const categorySelectorProps = {
            classFullName: this.classFullName,
            code: this.createCode(iModelDb, definitionModelId, name),
            model: definitionModelId,
            categories,
            isPrivate: false,
        };
        return new CategorySelector(categorySelectorProps, iModelDb);
    }
    /**
     * Insert a CategorySelector to select which categories are displayed by a ViewDefinition.
     * @param iModelDb Insert into this iModel
     * @param definitionModelId Insert the new CategorySelector into this DefinitionModel
     * @param name The name of the CategorySelector
     * @param categories Array of categories to select for display
     * @returns The Id of the newly inserted CategorySelector element.
     * @throws [[IModelError]] if unable to insert the element.
     */
    static insert(iModelDb, definitionModelId, name, categories) {
        const categorySelector = this.create(iModelDb, definitionModelId, name, categories);
        return iModelDb.elements.insertElement(categorySelector.toJSON());
    }
}
exports.CategorySelector = CategorySelector;
/**
 * The definition element for a view. ViewDefinitions specify the area/volume that is viewed, the Ids of a DisplayStyle and a CategorySelector,
 * plus additional view-specific parameters in their [[Element.jsonProperties]].
 * Subclasses of ViewDefinition determine which model(s) are viewed.
 * @note ViewDefinition is only available in the backend. See [ViewState]($frontend) for usage in the frontend.
 * @public @preview
 */
class ViewDefinition extends Element_1.DefinitionElement {
    static get className() { return "ViewDefinition"; }
    /** The element Id of the [[CategorySelector]] for this ViewDefinition */
    categorySelectorId;
    /** The element Id of the [[DisplayStyle]] for this ViewDefinition */
    displayStyleId;
    constructor(props, iModel) {
        super(props, iModel);
        this.categorySelectorId = core_bentley_1.Id64.fromJSON(props.categorySelectorId);
        if (!core_bentley_1.Id64.isValid(this.categorySelectorId))
            throw new core_common_1.IModelError(core_bentley_1.IModelStatus.BadArg, `categorySelectorId is invalid`);
        this.displayStyleId = core_bentley_1.Id64.fromJSON(props.displayStyleId);
        if (!core_bentley_1.Id64.isValid(this.displayStyleId))
            throw new core_common_1.IModelError(core_bentley_1.IModelStatus.BadArg, `displayStyleId is invalid`);
    }
    /**
     * ViewDefinition custom HandledProps includes 'categorySelector', and 'displayStyle'.
     * @inheritdoc
     * @beta
     */
    static _customHandledProps = [
        { propertyName: "categorySelector", source: "Class" },
        { propertyName: "displayStyle", source: "Class" },
    ];
    /**
     * ViewDefinition deserializes 'categorySelector', and 'displayStyle'.
     * @inheritdoc
     * @beta
     */
    static deserialize(props) {
        const elProps = super.deserialize(props);
        const instance = props.row;
        if (instance.isPrivate !== undefined)
            elProps.isPrivate = instance.isPrivate;
        elProps.categorySelectorId = instance.categorySelector.id;
        elProps.displayStyleId = instance.displayStyle.id;
        return elProps;
    }
    /**
     * ViewDefinition serializes 'categorySelector', and 'displayStyle'.
     * @inheritdoc
     * @beta
     */
    static serialize(props, _iModel) {
        const inst = super.serialize(props, _iModel);
        inst.categorySelector.id = props.categorySelectorId;
        inst.displayStyle.id = props.displayStyleId;
        return inst;
    }
    toJSON() {
        const json = super.toJSON();
        json.categorySelectorId = this.categorySelectorId;
        json.displayStyleId = this.displayStyleId;
        return json;
    }
    collectReferenceIds(referenceIds) {
        super.collectReferenceIds(referenceIds);
        referenceIds.addElement(this.categorySelectorId);
        referenceIds.addElement(this.displayStyleId);
        const acsId = this.getAuxiliaryCoordinateSystemId();
        if (core_bentley_1.Id64.isValidId64(acsId)) {
            referenceIds.addElement(acsId);
        }
    }
    /** @beta */
    static requiredReferenceKeys = [...super.requiredReferenceKeys, "categorySelectorId", "displayStyleId"];
    /** @alpha */
    static requiredReferenceKeyTypeMap = {
        ...super.requiredReferenceKeyTypeMap,
        categorySelectorId: core_common_1.ConcreteEntityTypes.Element,
        displayStyleId: core_common_1.ConcreteEntityTypes.Element,
    };
    /** @beta */
    static async onCloned(context, sourceElementProps, targetElementProps) {
        await super.onCloned(context, sourceElementProps, targetElementProps);
        if (context.isBetweenIModels && targetElementProps.jsonProperties && targetElementProps.jsonProperties.viewDetails) {
            const acsId = core_bentley_1.Id64.fromJSON(targetElementProps.jsonProperties.viewDetails.acs);
            if (core_bentley_1.Id64.isValidId64(acsId)) {
                targetElementProps.jsonProperties.viewDetails.acs = context.findTargetElementId(acsId);
            }
        }
    }
    /** Type guard for `instanceof ViewDefinition3d`  */
    isView3d() { return this instanceof ViewDefinition3d; }
    /** Type guard for 'instanceof ViewDefinition2d` */
    isView2d() { return this instanceof ViewDefinition2d; }
    /** Type guard for `instanceof SpatialViewDefinition` */
    isSpatialView() { return this instanceof SpatialViewDefinition; }
    /** Type guard for 'instanceof DrawingViewDefinition' */
    isDrawingView() { return this instanceof DrawingViewDefinition; }
    /** Load this view's DisplayStyle from the IModelDb. */
    loadDisplayStyle() { return this.iModel.elements.getElement(this.displayStyleId); }
    /** Load this view's CategorySelector from the IModelDb. */
    loadCategorySelector() { return this.iModel.elements.getElement(this.categorySelectorId); }
    /** The Id of the AuxiliaryCoordinateSystem for this ViewDefinition, or an invalid Id if no ACS is defined. */
    getAuxiliaryCoordinateSystemId() {
        return this.details.auxiliaryCoordinateSystemId;
    }
    /** Set or clear the AuxiliaryCoordinateSystem for this ViewDefinition.
     * @param acsId The Id of the new AuxiliaryCoordinateSystem. If `Id64.invalid` is passed, then no AuxiliaryCoordinateSystem will be used.
     */
    setAuxiliaryCoordinateSystemId(acsId) {
        this.details.auxiliaryCoordinateSystemId = acsId;
    }
    /** Create a Code for a ViewDefinition 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 to contain the ViewDefinition and provides the scope for its name.
     * @param codeValue The ViewDefinition name
     */
    static createCode(iModel, scopeModelId, codeValue) {
        const codeSpec = iModel.codeSpecs.getByName(core_common_1.BisCodeSpec.viewDefinition);
        return new core_common_1.Code({ spec: codeSpec.id, scope: scopeModelId, value: codeValue });
    }
}
exports.ViewDefinition = ViewDefinition;
/** Defines a view of one or more 3d models.
 * @public @preview
 */
class ViewDefinition3d extends ViewDefinition {
    _details;
    static get className() { return "ViewDefinition3d"; }
    /** If true, camera is used. Otherwise, use an orthographic projection. */
    cameraOn;
    /** The lower left back corner of the view frustum. */
    origin;
    /** The extent (size) of the view frustum, in meters, along its x,y,z axes. */
    extents;
    /** Rotation from world coordinates to view coordinates. */
    angles;
    /** The camera used for this view, if `cameraOn` is true. */
    camera;
    constructor(props, iModel) {
        super(props, iModel);
        this.cameraOn = core_bentley_1.JsonUtils.asBool(props.cameraOn);
        this.origin = core_geometry_1.Point3d.fromJSON(props.origin);
        this.extents = core_geometry_1.Vector3d.fromJSON(props.extents);
        this.angles = core_geometry_1.YawPitchRollAngles.fromJSON(props.angles);
        this.camera = new core_common_1.Camera(props.camera);
        this._details = new core_common_1.ViewDetails3d(this.jsonProperties);
    }
    /**
     * ViewDefinition3d custom HandledProps includes 'eyePoint', 'focusDistance', 'lensAngle', 'yaw', 'pitch', 'roll',
     * 'origin', 'extents', and 'isCameraOn'.
     * @inheritdoc
     * @beta
     */
    static _customHandledProps = [
        { propertyName: "eyePoint", source: "Class" },
        { propertyName: "focusDistance", source: "Class" },
        { propertyName: "lensAngle", source: "Class" },
        { propertyName: "yaw", source: "Class" },
        { propertyName: "roll", source: "Class" },
        { propertyName: "pitch", source: "Class" },
        { propertyName: "origin", source: "Class" },
        { propertyName: "extents", source: "Class" },
        { propertyName: "isCameraOn", source: "Class" },
    ];
    /**
     * ViewDefinition3d deserializes 'eyePoint', 'focusDistance', 'lensAngle', 'yaw', 'pitch', 'roll',
     * 'origin', 'extents', and 'isCameraOn'.
     * @inheritdoc
     * @beta
     */
    static deserialize(props) {
        const instance = props.row;
        const elProps = super.deserialize(props);
        // ViewDefinition3dProps
        elProps.cameraOn = instance.isCameraOn;
        elProps.origin = [instance.origin.x, instance.origin.y, instance.origin.z];
        elProps.extents = [instance.extents.x, instance.extents.y, instance.extents.z];
        elProps.camera = { eye: [instance.eyePoint.x, instance.eyePoint.y, instance.eyePoint.z], focusDist: instance.focusDistance, lens: core_geometry_1.Angle.createRadians(instance.lensAngle).toJSON() };
        elProps.angles = core_geometry_1.YawPitchRollAngles.createDegrees(instance.yaw ?? 0, instance.pitch ?? 0, instance.roll ?? 0).toJSON();
        return elProps;
    }
    /**
     * ViewDefinition3d serializes 'eyePoint', 'focusDistance', 'lensAngle', 'yaw', 'pitch', 'roll',
     * 'origin', 'extents', and 'isCameraOn'.
     * @inheritdoc
     * @beta
     */
    static serialize(props, _iModel) {
        const row = super.serialize(props, _iModel);
        row.isCameraOn = props.cameraOn;
        row.eyePoint = props.camera.eye;
        row.focusDistance = props.camera.focusDist;
        row.lensAngle = props.camera.lens;
        if (props.angles) {
            row.yaw = props.angles.yaw;
            row.roll = props.angles.roll;
            row.pitch = props.angles.pitch;
        }
        return row;
    }
    toJSON() {
        const val = super.toJSON();
        val.cameraOn = this.cameraOn;
        val.origin = this.origin;
        val.extents = this.extents;
        val.angles = this.angles;
        val.camera = this.camera;
        return val;
    }
    /** Provides access to optional detail settings for this view. */
    get details() { return this._details; }
    /** Load this view's DisplayStyle3d from the IModelDb. */
    loadDisplayStyle3d() { return this.iModel.elements.getElement(this.displayStyleId); }
}
exports.ViewDefinition3d = ViewDefinition3d;
/** Defines a view of one or more SpatialModels.
 * The list of viewed models is stored by the ModelSelector.
 *
 * This is how a SpatialViewDefinition selects the elements to display:
 *
 *  SpatialViewDefinition
 *    * ModelSelector
 *        * ModelIds  -------> SpatialModels    <----------GeometricElement3d.Model
 *    * CategorySelector
 *        * CategoryIds -----> SpatialCategories <----------GeometricElement3d.Category
 * @public @preview
 */
class SpatialViewDefinition extends ViewDefinition3d {
    static get className() { return "SpatialViewDefinition"; }
    /** The Id of the [[ModelSelector]] for this SpatialViewDefinition. */
    modelSelectorId;
    constructor(props, iModel) {
        super(props, iModel);
        this.modelSelectorId = core_bentley_1.Id64.fromJSON(props.modelSelectorId);
        if (!core_bentley_1.Id64.isValid(this.modelSelectorId))
            throw new core_common_1.IModelError(core_bentley_1.IModelStatus.BadArg, `modelSelectorId is invalid`);
    }
    /** Construct a SpatialViewDefinition from its JSON representation. */
    static fromJSON(props, iModel) {
        return new SpatialViewDefinition({ ...props, classFullName: this.classFullName }, iModel);
    }
    toJSON() {
        const json = super.toJSON();
        json.modelSelectorId = this.modelSelectorId;
        return json;
    }
    /**
     * SpatialViewDefinition custom HandledProps includes 'modelSelector'.
     * @inheritdoc
     * @beta
     */
    static _customHandledProps = [
        { propertyName: "modelSelector", source: "Class" },
    ];
    /**
     * SpatialViewDefinition deserializes 'modelSelector'.
     * @inheritdoc
     * @beta
     */
    static deserialize(props) {
        const elProps = super.deserialize(props);
        const instance = props.row;
        elProps.modelSelectorId = instance.modelSelector.id;
        return elProps;
    }
    /**
     * SpatialViewDefinition serializes 'modelSelector'.
     * @inheritdoc
     * @beta
     */
    static serialize(props, _iModel) {
        const inst = super.serialize(props, _iModel);
        inst.modelSelector.id = props.modelSelectorId;
        return inst;
    }
    collectReferenceIds(referenceIds) {
        super.collectReferenceIds(referenceIds);
        referenceIds.addElement(this.modelSelectorId);
    }
    /** @beta */
    static requiredReferenceKeys = [...super.requiredReferenceKeys, "modelSelectorId"];
    /** @alpha */
    static requiredReferenceKeyTypeMap = {
        ...super.requiredReferenceKeyTypeMap,
        modelSelectorId: core_common_1.ConcreteEntityTypes.Element,
    };
    /** Load this view's ModelSelector from the IModelDb. */
    loadModelSelector() { return this.iModel.elements.getElement(this.modelSelectorId); }
    /**
     * Create a SpatialViewDefinition with the camera turned on.
     * @param iModelDb The iModel
     * @param definitionModelId The [[DefinitionModel]]
     * @param name The name/CodeValue of the view
     * @param modelSelectorId The [[ModelSelector]] that this view should use
     * @param categorySelectorId The [[CategorySelector]] that this view should use
     * @param displayStyleId The [[DisplayStyle3d]] that this view should use
     * @param range Defines the view origin and extents
     * @param standardView Optionally defines the view's rotation
     * @param cameraAngle Camera angle in radians.
     * @returns The newly constructed SpatialViewDefinition element
     * @throws [[IModelError]] if there is a problem creating the view
     */
    static createWithCamera(iModelDb, definitionModelId, name, modelSelectorId, categorySelectorId, displayStyleId, range, standardView = core_geometry_1.StandardViewIndex.Iso, cameraAngle = core_geometry_1.Angle.piOver2Radians) {
        const rotation = core_geometry_1.Matrix3d.createStandardWorldToView(standardView);
        const angles = core_geometry_1.YawPitchRollAngles.createFromMatrix3d(rotation);
        const rotationTransform = core_geometry_1.Transform.createOriginAndMatrix(undefined, rotation);
        const rotatedRange = rotationTransform.multiplyRange(range);
        const cameraDistance = 2 * (rotatedRange.diagonal().magnitudeXY() / 2.0) / Math.tan(cameraAngle / 2.0);
        const cameraLocation = rotatedRange.diagonalFractionToPoint(.5); // Start at center.
        cameraLocation.z += cameraDistance; // Back up by camera distance.
        rotation.multiplyTransposeVectorInPlace(cameraLocation);
        const viewDefinitionProps = {
            classFullName: this.classFullName,
            model: definitionModelId,
            code: this.createCode(iModelDb, definitionModelId, name),
            modelSelectorId,
            categorySelectorId,
            displayStyleId,
            origin: rotation.multiplyTransposeXYZ(rotatedRange.low.x, rotatedRange.low.y, rotatedRange.low.z),
            extents: rotatedRange.diagonal(),
            angles,
            cameraOn: true,
            camera: { lens: { radians: cameraAngle }, focusDist: cameraDistance, eye: cameraLocation },
        };
        return new SpatialViewDefinition(viewDefinitionProps, iModelDb);
    }
    /**
     * Insert an SpatialViewDefinition with the camera turned on.
     * @see [[createWithCamera]] for details.
     * @returns The Id of the newly inserted SpatialViewDefinition element
     * @throws [[IModelError]] if there is an insert problem.
     */
    static insertWithCamera(iModelDb, definitionModelId, name, modelSelectorId, categorySelectorId, displayStyleId, range, standardView = core_geometry_1.StandardViewIndex.Iso, cameraAngle = core_geometry_1.Angle.piOver2Radians) {
        const viewDefinition = this.createWithCamera(iModelDb, definitionModelId, name, modelSelectorId, categorySelectorId, displayStyleId, range, standardView, cameraAngle);
        return iModelDb.elements.insertElement(viewDefinition.toJSON());
    }
}
exports.SpatialViewDefinition = SpatialViewDefinition;
/** Defines a spatial view that displays geometry on the image plane using a parallel orthographic projection.
 * See [how to create a OrthographicViewDefinition]($docs/learning/backend/CreateElements.md#OrthographicViewDefinition).
 * @public @preview
 */
class OrthographicViewDefinition extends SpatialViewDefinition {
    static get className() { return "OrthographicViewDefinition"; }
    constructor(props, iModel) { super(props, iModel); }
    /**
     * Create an OrthographicViewDefinition
     * @param iModelDb The iModel
     * @param definitionModelId The [[DefinitionModel]]
     * @param name The name/CodeValue of the view
     * @param modelSelectorId The [[ModelSelector]] that this view should use
     * @param categorySelectorId The [[CategorySelector]] that this view should use
     * @param displayStyleId The [[DisplayStyle3d]] that this view should use
     * @param range Defines the view origin and extents
     * @param standardView Optionally defines the view's rotation
     * @returns The newly constructed OrthographicViewDefinition element
     * @throws [[IModelError]] if there is a problem creating the view
     */
    static create(iModelDb, definitionModelId, name, modelSelectorId, categorySelectorId, displayStyleId, range, standardView = core_geometry_1.StandardViewIndex.Iso) {
        const rotation = core_geometry_1.Matrix3d.createStandardWorldToView(standardView);
        const angles = core_geometry_1.YawPitchRollAngles.createFromMatrix3d(rotation);
        const rotationTransform = core_geometry_1.Transform.createOriginAndMatrix(undefined, rotation);
        const rotatedRange = rotationTransform.multiplyRange(range);
        const viewDefinitionProps = {
            classFullName: this.classFullName,
            model: definitionModelId,
            code: this.createCode(iModelDb, definitionModelId, name),
            modelSelectorId,
            categorySelectorId,
            displayStyleId,
            origin: rotation.multiplyTransposeXYZ(rotatedRange.low.x, rotatedRange.low.y, rotatedRange.low.z),
            extents: rotatedRange.diagonal(),
            angles,
            cameraOn: false,
            camera: new core_common_1.Camera(), // not used when cameraOn === false
        };
        return new OrthographicViewDefinition(viewDefinitionProps, iModelDb);
    }
    /**
     * Insert an OrthographicViewDefinition
     * @param iModelDb Insert into this iModel
     * @param definitionModelId Insert the new OrthographicViewDefinition into this DefinitionModel
     * @param name The name/CodeValue of the view
     * @param modelSelectorId The [[ModelSelector]] that this view should use
     * @param categorySelectorId The [[CategorySelector]] that this view should use
     * @param displayStyleId The [[DisplayStyle3d]] that this view should use
     * @param range Defines the view origin and extents
     * @param standardView Optionally defines the view's rotation
     * @returns The Id of the newly inserted OrthographicViewDefinition element
     * @throws [[IModelError]] if there is an insert problem.
     */
    static insert(iModelDb, definitionModelId, name, modelSelectorId, categorySelectorId, displayStyleId, range, standardView = core_geometry_1.StandardViewIndex.Iso) {
        const viewDefinition = this.create(iModelDb, definitionModelId, name, modelSelectorId, categorySelectorId, displayStyleId, range, standardView);
        return iModelDb.elements.insertElement(viewDefinition.toJSON());
    }
    /** Set a new viewed range without changing the rotation or any other properties. */
    setRange(range) {
        const rotation = this.angles.toMatrix3d();
        const rotationTransform = core_geometry_1.Transform.createOriginAndMatrix(undefined, rotation);
        const rotatedRange = rotationTransform.multiplyRange(range);
        this.origin = core_geometry_1.Point3d.createFrom(rotation.multiplyTransposeXYZ(rotatedRange.low.x, rotatedRange.low.y, rotatedRange.low.z));
        this.extents = rotatedRange.diagonal();
    }
}
exports.OrthographicViewDefinition = OrthographicViewDefinition;
/** Defines a view of a single 2d model. Each 2d model has its own coordinate system, so only one may appear per view.
 * @public @preview
 */
class ViewDefinition2d extends ViewDefinition {
    _details;
    static get className() { return "ViewDefinition2d"; }
    /** The Id of the Model displayed by this view. */
    baseModelId;
    /** The lower-left corner of this view in Model coordinates. */
    origin;
    /** The delta (size) of this view, in meters, aligned with view x,y. */
    delta;
    /** The rotation of this view. */
    angle;
    constructor(props, iModel) {
        super(props, iModel);
        this.baseModelId = core_bentley_1.Id64.fromJSON(props.baseModelId);
        this.origin = core_geometry_1.Point2d.fromJSON(props.origin);
        this.delta = core_geometry_1.Point2d.fromJSON(props.delta);
        this.angle = core_geometry_1.Angle.fromJSON(props.angle);
        this._details = new core_common_1.ViewDetails(this.jsonProperties);
    }
    toJSON() {
        const val = super.toJSON();
        val.baseModelId = this.baseModelId;
        val.origin = this.origin;
        val.delta = this.delta;
        val.angle = this.angle;
        return val;
    }
    /**
     * ViewDefinition2d custom HandledProps includes 'baseModel', 'origin', 'extents', and 'rotationAngle'.
     * @inheritdoc
     * @beta
     */
    static _customHandledProps = [
        { propertyName: "baseModel", source: "Class" },
        { propertyName: "origin", source: "Class" },
        { propertyName: "extents", source: "Class" },
        { propertyName: "rotationAngle", source: "Class" },
    ];
    /**
     * ViewDefinition2d deserializes 'baseModel', 'origin', 'extents', and 'rotationAngle'.
     * @inheritdoc
     * @beta
     */
    static deserialize(props) {
        const elProps = super.deserialize(props);
        const instance = props.row;
        elProps.baseModelId = instance.baseModel.id;
        elProps.origin = [instance.origin.x, instance.origin.y];
        elProps.delta = [instance.extents.x, instance.extents.y];
        elProps.angle = instance.rotationAngle;
        return elProps;
    }
    /**
     * ViewDefinition2d serializes 'baseModel', 'origin', 'extents', and 'rotationAngle'.
     * @inheritdoc
     * @beta
     */
    static serialize(props, _iModel) {
        const inst = super.serialize(props, _iModel);
        inst.baseModel.id = props.baseModelId;
        inst.origin = props.origin;
        inst.extents = props.delta;
        inst.rotationAngle = props.angle;
        return inst;
    }
    collectReferenceIds(referenceIds) {
        super.collectReferenceIds(referenceIds);
        referenceIds.addElement(this.baseModelId);
    }
    /** Provides access to optional detail settings for this view. */
    get details() { return this._details; }
    /** Load this view's DisplayStyle2d from the IModelDb. */
    loadDisplayStyle2d() { return this.iModel.elements.getElement(this.displayStyleId); }
}
exports.ViewDefinition2d = ViewDefinition2d;
/** Defines a view of a [[DrawingModel]].
 * @public @preview
 */
class DrawingViewDefinition extends ViewDefinition2d {
    static get className() { return "DrawingViewDefinition"; }
    constructor(props, iModel) {
        super(props, iModel);
    }
    /** Create a DrawingViewDefinition
     * @param iModelDb The iModel
     * @param definitionModelId The [[DefinitionModel]]
     * @param name The name/CodeValue of the view
     * @param baseModelId The base [[DrawingModel]]
     * @param categorySelectorId The [[CategorySelector]] that this view should use
     * @param displayStyleId The [[DisplayStyle2d]] that this view should use
     * @param range Defines the view origin and extents
     * @throws [[IModelError]] if there is a problem creating the element.
     */
    static create(iModelDb, definitionModelId, name, baseModelId, categorySelectorId, displayStyleId, range) {
        const viewDefinitionProps = {
            classFullName: this.classFullName,
            model: definitionModelId,
            code: this.createCode(iModelDb, definitionModelId, name),
            baseModelId,
            categorySelectorId,
            displayStyleId,
            origin: { x: range.low.x, y: range.low.y },
            delta: range.diagonal(),
            angle: 0,
        };
        return new DrawingViewDefinition(viewDefinitionProps, iModelDb);
    }
    /** Construct a DrawingViewDefinition from its JSON representation. */
    static fromJSON(props, iModel) {
        return new DrawingViewDefinition({ ...props, classFullName: this.classFullName }, iModel);
    }
    /** Insert a DrawingViewDefinition
     * @param iModelDb Insert into this iModel
     * @param definitionModelId Insert the new DrawingViewDefinition into this [[DefinitionModel]]
     * @param name The name/CodeValue of the view
     * @param baseModelId The base [[DrawingModel]]
     * @param categorySelectorId The [[CategorySelector]] that this view should use
     * @param displayStyleId The [[DisplayStyle2d]] that this view should use
     * @param range Defines the view origin and extents
     * @throws [[IModelError]] if there is an insert problem.
     */
    static insert(iModelDb, definitionModelId, name, baseModelId, categorySelectorId, displayStyleId, range) {
        const viewDefinition = this.create(iModelDb, definitionModelId, name, baseModelId, categorySelectorId, displayStyleId, range);
        return iModelDb.elements.insertElement(viewDefinition.toJSON());
    }
}
exports.DrawingViewDefinition = DrawingViewDefinition;
/** Defines a view of a [[SheetModel]].
 * @public @preview
 */
class SheetViewDefinition extends ViewDefinition2d {
    static get className() { return "SheetViewDefinition"; }
    constructor(props, iModel) {
        super(props, iModel);
    }
    /** Create a SheetViewDefinition */
    static create(args) {
        const { baseModelId, categorySelectorId, displayStyleId, range } = args;
        const props = {
            classFullName: this.classFullName,
            model: args.definitionModelId,
            code: this.createCode(args.iModel, args.definitionModelId, args.name),
            baseModelId,
            categorySelectorId,
            displayStyleId,
            origin: { x: range.low.x, y: range.low.y },
            delta: range.diagonal(),
            angle: 0,
        };
        return new SheetViewDefinition(props, args.iModel);
    }
    /** Insert a SheetViewDefinition into an IModelDb */
    static insert(args) {
        const view = this.create(args);
        return args.iModel.elements.insertElement(view.toJSON());
    }
    /** Create a SheetViewDefinition from JSON props */
    static fromJSON(props, iModel) {
        return new SheetViewDefinition({ ...props, classFullName: this.classFullName }, iModel);
    }
}
exports.SheetViewDefinition = SheetViewDefinition;
/** A ViewDefinition used to display a 2d template model.
 * @internal
 */
class TemplateViewDefinition2d extends ViewDefinition2d {
    static get className() { return "TemplateViewDefinition2d"; }
}
exports.TemplateViewDefinition2d = TemplateViewDefinition2d;
/** A ViewDefinition used to display a 3d template model.
 * @internal
 */
class TemplateViewDefinition3d extends ViewDefinition3d {
    static get className() { return "TemplateViewDefinition3d"; }
}
exports.TemplateViewDefinition3d = TemplateViewDefinition3d;
/** An auxiliary coordinate system element. Auxiliary coordinate systems can be used by views to show
 * coordinate information in different units and/or orientations.
 * @public @preview
 */
class AuxCoordSystem extends Element_1.DefinitionElement {
    static get className() { return "AuxCoordSystem"; }
    type;
    description;
    constructor(props, iModel) {
        super(props, iModel);
        this.type = props.type;
        this.description = props.description;
    }
}
exports.AuxCoordSystem = AuxCoordSystem;
/** A 2d auxiliary coordinate system.
 * @public @preview
 */
class AuxCoordSystem2d extends AuxCoordSystem {
    static get className() { return "AuxCoordSystem2d"; }
    origin;
    angle;
    constructor(props, iModel) {
        super(props, iModel);
        this.origin = props.origin ? core_geometry_1.Point2d.fromJSON(props.origin) : undefined;
        this.angle = props.angle ? core_geometry_1.Angle.fromJSON(props.angle).degrees : undefined;
    }
    /** Create a Code for a AuxCoordSystem2d 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 AuxCoordSystem2d element and provides the scope for its name.
     * @param codeValue The AuxCoordSystem2d name
     */
    static createCode(iModel, scopeModelId, codeValue) {
        const codeSpec = iModel.codeSpecs.getByName(core_common_1.BisCodeSpec.auxCoordSystem2d);
        return new core_common_1.Code({ spec: codeSpec.id, scope: scopeModelId, value: codeValue });
    }
}
exports.AuxCoordSystem2d = AuxCoordSystem2d;
/** A 3d auxiliary coordinate system.
 * @public @preview
 */
class AuxCoordSystem3d extends AuxCoordSystem {
    static get className() { return "AuxCoordSystem3d"; }
    origin;
    yaw;
    pitch;
    roll;
    constructor(props, iModel) {
        super(props, iModel);
        this.origin = props.origin ? core_geometry_1.Point3d.fromJSON(props.origin) : undefined;
        this.yaw = props.yaw ? core_geometry_1.Angle.fromJSON(props.yaw).degrees : undefined;
        this.pitch = props.pitch ? core_geometry_1.Angle.fromJSON(props.pitch).degrees : undefined;
        this.roll = props.roll ? core_geometry_1.Angle.fromJSON(props.roll).degrees : undefined;
    }
    /** Create a Code for a AuxCoordSystem3d 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 AuxCoordSystem3d element and provides the scope for its name.
     * @param codeValue The AuxCoordSystem3d name
     */
    static createCode(iModel, scopeModelId, codeValue) {
        const codeSpec = iModel.codeSpecs.getByName(core_common_1.BisCodeSpec.auxCoordSystem3d);
        return new core_common_1.Code({ spec: codeSpec.id, scope: scopeModelId, value: codeValue });
    }
}
exports.AuxCoordSystem3d = AuxCoordSystem3d;
/** A spatial auxiliary coordinate system.
 * @public @preview
 */
class AuxCoordSystemSpatial extends AuxCoordSystem3d {
    static get className() { return "AuxCoordSystemSpatial"; }
    /** Create a Code for a AuxCoordSystemSpatial 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 AuxCoordSystemSpatial element and provides the scope for its name.
     * @param codeValue The AuxCoordSystemSpatial name
     */
    static createCode(iModel, scopeModelId, codeValue) {
        const codeSpec = iModel.codeSpecs.getByName(core_common_1.BisCodeSpec.auxCoordSystemSpatial);
        return new core_common_1.Code({ spec: codeSpec.id, scope: scopeModelId, value: codeValue });
    }
}
exports.AuxCoordSystemSpatial = AuxCoordSystemSpatial;
/** Represents an *attachment* of a [[ViewDefinition]] to a [[Sheet]].
 * @public @preview
 */
class ViewAttachment extends Element_1.GraphicalElement2d {
    static get className() { return "ViewAttachment"; }
    view;
    constructor(props, iModel) {
        super(props, iModel);
        this.view = new core_common_1.RelatedElement(props.view);
        // ###NOTE: scale, displayPriority, and clipping vectors are stored in ViewAttachmentProps.jsonProperties.
    }
    collectReferenceIds(referenceIds) {
        super.collectReferenceIds(referenceIds);
        referenceIds.addElement(this.view.id);
    }
}
exports.ViewAttachment = ViewAttachment;
/** The position in space of a Light.
 * @internal
 */
class LightLocation extends Element_1.SpatialLocationElement {
    static get className() { return "LightLocation"; }
    /** Whether this light is currently turned on. */
    enabled;
    constructor(props, iModel) {
        super(props, iModel);
        this.enabled = props.enabled;
    }
}
exports.LightLocation = LightLocation;
//# sourceMappingURL=ViewDefinition.js.map