import { Camera, Matrix } from './babylonjs-import';
import { ProjectionMatrix } from '../math/ProjectionMatrix';

export class ShortFrustumProjectionMatrixState {
    private readonly _invertedShortFrustumProjectionMatrix: Matrix = Matrix.Identity();
    private readonly _shortFrustumProjectionMatrix: Matrix = Matrix.Identity();
    private readonly _originalProjectionMatrix: Matrix = Matrix.Identity();
    public readonly depthRenderCameraMinZ = 0.25;
    public readonly depthRenderCameraMaxZ = 600.0;
    private _camera: Camera;

    private calculateShortFrustumProjectionMatrix(camera: Camera): void {
        this._originalProjectionMatrix.copyFrom(camera.getProjectionMatrix());
        ProjectionMatrix.getToRef(
            camera,
            { minZ: this.depthRenderCameraMinZ, maxZ: this.depthRenderCameraMaxZ },
            this._shortFrustumProjectionMatrix
        );
        this._shortFrustumProjectionMatrix.invertToRef(this._invertedShortFrustumProjectionMatrix);
    }

    private updateMatricesIfNeeded(): void {
        const currentProjectionMatrix = this._camera.getProjectionMatrix();
        const savedProjectionMatrix = this._originalProjectionMatrix;

        if (currentProjectionMatrix.updateFlag !== savedProjectionMatrix.updateFlag) {
            this.calculateShortFrustumProjectionMatrix(this._camera);
        }
    }

    public getProjectionMatrix(): Matrix {
        this.updateMatricesIfNeeded();
        return this._shortFrustumProjectionMatrix;
    }

    public getInvertedProjectionMatrix(): Matrix {
        this.updateMatricesIfNeeded();
        return this._invertedShortFrustumProjectionMatrix;
    }

    constructor(camera: Camera) {
        this._camera = camera;
        this.calculateShortFrustumProjectionMatrix(camera);
    }
}
