/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module WebGL
 */
import { dispose } from "@itwin/core-bentley";
import { FeatureIndexType, PolylineTypeFlags, RenderMode } from "@itwin/core-common";
import { RenderMemory } from "../RenderMemory";
import { LUTGeometry, PolylineBuffers } from "./CachedGeometry";
import { LineCode } from "./LineCode";
import { GL } from "./GL";
import { System } from "./System";
import { VertexLUT } from "./VertexLUT";
/** @internal */
export class PolylineGeometry extends LUTGeometry {
    get lutBuffers() { return this._buffers.buffers; }
    constructor(lut, buffers, params, viOrigin) {
        super(viOrigin);
        this.renderGeometryType = "polyline";
        this.noDispose = false;
        this.isInstanceable = undefined === viOrigin;
        this.vertexParams = params.vertices.qparams;
        this._hasFeatures = FeatureIndexType.Empty !== params.vertices.featureIndexType;
        this.lineWeight = params.weight;
        this.lineCode = LineCode.valueFromLinePixels(params.linePixels);
        this.type = params.type;
        this._isPlanar = params.isPlanar;
        this.lut = lut;
        this.numIndices = params.polyline.indices.length;
        this._buffers = buffers;
    }
    get isDisposed() { return this._buffers.isDisposed && this.lut.isDisposed; }
    dispose() {
        if (!this.noDispose) {
            dispose(this.lut);
            dispose(this._buffers);
        }
    }
    collectStatistics(stats) {
        this._buffers.collectStatistics(stats, RenderMemory.BufferType.Polylines);
        stats.addVertexTable(this.lut.bytesUsed);
    }
    get isAnyEdge() { return PolylineTypeFlags.Normal !== this.type; }
    get isNormalEdge() { return PolylineTypeFlags.Edge === this.type; }
    get isOutlineEdge() { return PolylineTypeFlags.Outline === this.type; }
    get renderOrder() {
        if (this.isAnyEdge)
            return this.isPlanar ? 14 /* RenderOrder.PlanarEdge */ : 6 /* RenderOrder.Edge */;
        else
            return this.isPlanar ? 13 /* RenderOrder.PlanarLinear */ : 5 /* RenderOrder.Linear */;
    }
    _wantWoWReversal(_target) { return true; }
    get polylineBuffers() { return this._buffers; }
    _computeEdgePass(target, colorInfo) {
        const vf = target.currentViewFlags;
        if (RenderMode.SmoothShade === vf.renderMode && !vf.visibleEdges)
            return "none";
        // Only want to return Translucent for edges if rendering in Wireframe mode ###TODO: what about overrides?
        const isTranslucent = RenderMode.Wireframe === vf.renderMode && vf.transparency && colorInfo.hasTranslucency;
        return isTranslucent ? "translucent" : "opaque-linear";
    }
    getPass(target) {
        const vf = target.currentViewFlags;
        if (this.isEdge) {
            let pass = this._computeEdgePass(target, this.lut.colorInfo);
            // Only display the outline in wireframe if Fill is off...
            if ("none" !== pass && this.isOutlineEdge && RenderMode.Wireframe === vf.renderMode && vf.fill)
                pass = "none";
            return pass;
        }
        const isTranslucent = vf.transparency && this.lut.colorInfo.hasTranslucency;
        return isTranslucent ? "translucent" : "opaque-linear";
    }
    get techniqueId() { return 1 /* TechniqueId.Polyline */; }
    get isPlanar() { return this._isPlanar; }
    get isEdge() { return this.isAnyEdge; }
    get qOrigin() { return this.lut.qOrigin; }
    get qScale() { return this.lut.qScale; }
    get numRgbaPerVertex() { return this.lut.numRgbaPerVertex; }
    get hasFeatures() { return this._hasFeatures; }
    _getLineWeight(params) {
        return this.isEdge ? params.target.computeEdgeWeight(params.renderPass, this.lineWeight) : this.lineWeight;
    }
    _getLineCode(params) {
        return this.isEdge ? params.target.computeEdgeLineCode(params.renderPass, this.lineCode) : this.lineCode;
    }
    getColor(target) {
        return this.isEdge ? target.computeEdgeColor(this.lut.colorInfo) : this.lut.colorInfo;
    }
    _draw(numInstances, instanceBuffersContainer) {
        const gl = System.instance;
        const bufs = instanceBuffersContainer !== undefined ? instanceBuffersContainer : this._buffers.buffers;
        bufs.bind();
        gl.drawArrays(GL.PrimitiveType.Triangles, 0, this.numIndices, numInstances);
        bufs.unbind();
    }
    static create(params, viewIndependentOrigin) {
        const lut = VertexLUT.createFromVertexTable(params.vertices);
        if (undefined === lut)
            return undefined;
        const buffers = PolylineBuffers.create(params.polyline);
        if (undefined === buffers)
            return undefined;
        return new PolylineGeometry(lut, buffers, params, viewIndependentOrigin);
    }
}
//# sourceMappingURL=Polyline.js.map