/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module Utils
 */
import { dispose } from "@itwin/core-bentley";
import { EmptyLocalization } from "@itwin/core-common";
import { IModelApp } from "../IModelApp";
import { ViewRect } from "../common/ViewRect";
import { PrimitiveBuilder } from "../internal/render/PrimitiveBuilder";
import { RenderGraphic } from "./RenderGraphic";
import { RenderSystem } from "./RenderSystem";
import { RenderTarget } from "./RenderTarget";
import { _implementationProhibited } from "../common/internal/Symbols";
/** Contains extensible mock implementations of the various components of a RenderSystem, intended for use in tests.
 * Use these for tests instead of the default RenderSystem wherever possible because:
 *  (1) Electron has a bug on Windows in which it fails to obtain a WebGLRenderingContext when running inside a VM (e.g., during CI job); and
 *  (2) To decouple the logic which uses aspects of the RenderSystem from the full implementation.
 * Any and all of these types can be extended for the purposes of specific tests.
 * To use this:
 *  (1) If overriding anything in the implementation supplied herein, pass a SystemFactory function to MockRender.App.systemFactory.
 *  (2) Call MockRender.App.startup() instead of IModelApp.startup() before tests begin.
 *  (3) Likewise call MockRender.App.shutdown() when finished. This resets the SystemFactory to its default.
 * @note The APIs within this namespace are intended *strictly* for use with unit tests.
 * @internal
 */
export var MockRender;
(function (MockRender) {
    var _a;
    /** @internal */
    class Target extends RenderTarget {
        constructor(_system) {
            super();
            this._system = _system;
            this[_a] = undefined;
        }
        get renderSystem() { return this._system; }
        get wantInvertBlackBackground() { return false; }
        get analysisFraction() { return 0; }
        set analysisFraction(_fraction) { }
        changeScene(_scene) { }
        changeDynamics(_dynamics) { }
        changeDecorations(_decs) { }
        changeRenderPlan(_plan) { }
        drawFrame(_sceneTime) { }
        updateViewRect() { return false; }
        readPixels(_rect, _selector, receiver, _excludeNonLocatable) { receiver(undefined); }
        get screenSpaceEffects() { return []; }
        set screenSpaceEffects(_effects) { }
    }
    _a = _implementationProhibited;
    MockRender.Target = Target;
    /** @internal */
    class OnScreenTarget extends Target {
        constructor(system, _canvas) {
            super(system);
            this._canvas = _canvas;
        }
        get viewRect() { return new ViewRect(0, 0, this._canvas.clientWidth, this._canvas.clientHeight); }
        setViewRect(_rect, _temp) { }
    }
    MockRender.OnScreenTarget = OnScreenTarget;
    /** @internal */
    class OffScreenTarget extends Target {
        constructor(system, _viewRect) {
            super(system);
            this._viewRect = _viewRect;
        }
        get viewRect() { return this._viewRect; }
        setViewRect(rect, _temp) { this._viewRect.setFrom(rect); }
    }
    MockRender.OffScreenTarget = OffScreenTarget;
    /** @internal */
    class Builder extends PrimitiveBuilder {
        constructor(system, options) {
            super(system, options);
        }
    }
    MockRender.Builder = Builder;
    class Graphic extends RenderGraphic {
        constructor() { super(); }
        dispose() { }
        collectStatistics(_stats) { }
        unionRange() { }
    }
    MockRender.Graphic = Graphic;
    class List extends Graphic {
        constructor(graphics) {
            super();
            this.graphics = graphics;
        }
        dispose() {
            for (const graphic of this.graphics)
                dispose(graphic);
            this.graphics.length = 0;
        }
    }
    MockRender.List = List;
    class Branch extends Graphic {
        constructor(branch, transform, options) {
            super();
            this.branch = branch;
            this.transform = transform;
            this.options = options;
        }
        dispose() { this.branch.dispose(); }
    }
    MockRender.Branch = Branch;
    class Batch extends Graphic {
        constructor(graphic, featureTable, range) {
            super();
            this.graphic = graphic;
            this.featureTable = featureTable;
            this.range = range;
        }
        dispose() {
            dispose(this.graphic);
        }
    }
    MockRender.Batch = Batch;
    /** @internal */
    class Geometry {
        dispose() { }
        collectStatistics() { }
    }
    MockRender.Geometry = Geometry;
    /** @internal */
    class AreaPattern {
        dispose() { }
        collectStatistics() { }
    }
    MockRender.AreaPattern = AreaPattern;
    class System extends RenderSystem {
        get isValid() { return true; }
        dispose() { }
        get maxTextureSize() { return 4096; }
        constructor() { super(); }
        /** @internal */
        doIdleWork() { return false; }
        /** @internal */
        createTarget(canvas) { return new OnScreenTarget(this, canvas); }
        /** @internal */
        createOffscreenTarget(rect) { return new OffScreenTarget(this, rect); }
        createGraphic(options) {
            return new Builder(this, options);
        }
        createGraphicList(primitives) { return new List(primitives); }
        createGraphicBranch(branch, transform, options) { return new Branch(branch, transform, options); }
        createBatch(graphic, features, range) { return new Batch(graphic, features, range); }
        /** @internal */
        createMesh(_params) { return new Graphic(); }
        /** @internal */
        createPolyline(_params) { return new Graphic(); }
        /** @internal */
        createPointString(_params) { return new Graphic(); }
        /** @internal */
        createPointCloud(_args, _imodel) { return new Graphic(); }
        createRenderGraphic() { return new Graphic(); }
        /** @internal */
        createMeshGeometry() { return new Geometry(); }
        /** @internal */
        createPolylineGeometry() { return new Geometry(); }
        /** @internal */
        createPointStringGeometry() { return new Geometry(); }
        /** @internal */
        createAreaPattern() { return new AreaPattern(); }
    }
    MockRender.System = System;
    /** An implementation of IModelApp which uses a MockRender.System by default. */
    class App {
        static async startup(opts) {
            opts = opts ? opts : {};
            opts.renderSys = this.systemFactory();
            opts.localization = opts.localization ?? new EmptyLocalization();
            await IModelApp.startup(opts);
        }
        static async shutdown() {
            this.systemFactory = () => App.createDefaultRenderSystem();
            await IModelApp.shutdown();
        }
        static createDefaultRenderSystem() { return new System(); }
    }
    App.systemFactory = () => App.createDefaultRenderSystem();
    MockRender.App = App;
})(MockRender || (MockRender = {}));
//# sourceMappingURL=MockRender.js.map