/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module Tiles
 */
import { ByteStream } from "@itwin/core-bentley";
import { Point3d, Transform } from "@itwin/core-geometry";
import { BatchType, decodeTileContentDescription, TileReadError, TileReadStatus, } from "@itwin/core-common";
import { IModelApp } from "../IModelApp";
import { GraphicBranch } from "../render/GraphicBranch";
import { convertFeatureTable, parseImdlDocument } from "../common/imdl/ParseImdlDocument";
import { decodeImdlGraphics } from "./internal";
/** Convert the byte array returned by [[TileAdmin.requestElementGraphics]] into a [[RenderGraphic]].
 * @param bytes The binary graphics data obtained from `requestElementGraphics`.
 * @param iModel The iModel with which the graphics are associated.
 * @param modelId The Id of the [[GeometricModelState]] with which the graphics are associated. Can be an invalid Id.
 * @param is3d True if the graphics are 3d.
 * @param options Options customizing how [Feature]($common)s within the graphic can be resymbolized; or false if you don't want to produce a batch.
 * @public
 * @extensions
 */
export async function readElementGraphics(bytes, iModel, modelId, is3d, options) {
    const stream = ByteStream.fromUint8Array(bytes);
    const reader = ImdlReader.create({
        stream, iModel, modelId, is3d, options,
        system: IModelApp.renderSystem,
    });
    const result = await reader.read();
    return result.graphic;
}
/** @internal */
export async function readImdlContent(args) {
    const isCanceled = args.isCanceled ?? (() => false);
    let content;
    try {
        content = decodeTileContentDescription({
            stream: args.stream,
            sizeMultiplier: args.sizeMultiplier,
            is2d: !args.is3d,
            options: IModelApp.tileAdmin,
            isVolumeClassifier: BatchType.VolumeClassifier === args.type,
            isLeaf: args.isLeaf,
        });
    }
    catch (e) {
        if (e instanceof TileReadError)
            return { isLeaf: true, readStatus: e.errorNumber };
        else
            throw e;
    }
    args.stream.reset();
    const parseOpts = {
        data: args.stream.readBytes(0, args.stream.length),
        batchModelId: args.modelId,
        is3d: args.is3d,
        maxVertexTableSize: IModelApp.renderSystem.maxTextureSize,
        omitEdges: false === args.loadEdges,
        createUntransformedRootNode: args.containsTransformNodes,
        modelGroups: args.modelGroups,
    };
    const document = args.parseDocument ? (await args.parseDocument(parseOpts)) : parseImdlDocument({ ...parseOpts, timeline: args.timeline });
    if (isCanceled())
        return { isLeaf: true, readStatus: TileReadStatus.Canceled };
    else if (typeof document === "number")
        return { isLeaf: true, readStatus: document };
    let graphic = await decodeImdlGraphics({
        system: args.system,
        iModel: args.iModel,
        document,
        isCanceled: args.isCanceled,
    });
    if (isCanceled())
        return { isLeaf: true, readStatus: TileReadStatus.Canceled };
    if (graphic && false !== args.options) {
        const featureTable = convertFeatureTable(document.featureTable, args.modelId);
        graphic = args.system.createBatch(graphic, featureTable, content.contentRange, args.options);
    }
    if (graphic && document.rtcCenter) {
        const rtcBranch = new GraphicBranch(true);
        rtcBranch.add(graphic);
        graphic = args.system.createBranch(rtcBranch, Transform.createTranslation(Point3d.fromJSON(document.rtcCenter)));
    }
    return {
        readStatus: TileReadStatus.Success,
        isLeaf: content.isLeaf,
        sizeMultiplier: content.sizeMultiplier,
        contentRange: content.contentRange.isNull ? undefined : content.contentRange,
        graphic,
        emptySubRangeMask: content.emptySubRangeMask,
    };
}
/** @internal */
export var ImdlReader;
(function (ImdlReader) {
    function create(args) {
        return {
            read: async () => readImdlContent(args),
        };
    }
    ImdlReader.create = create;
})(ImdlReader || (ImdlReader = {}));
//# sourceMappingURL=ImdlReader.js.map