import { WEBGL_CONTEXT_ATTRIBUTES } from '../constant';
import { BackendContext } from './backend-context';

const renderCanvasList: RenderCanvas[] = [];

export class RenderCanvas {
  public static from(canvas: HTMLCanvasElement | OffscreenCanvas, contextAttributes?: WebGLContextAttributes) {
    let renderCanvas = renderCanvasList.find((targetCanvas) => targetCanvas.canvas === canvas);
    if (renderCanvas) return renderCanvas;
    renderCanvas = new RenderCanvas(canvas, contextAttributes);
    renderCanvasList.push(renderCanvas);
    return renderCanvas;
  }

  private _canvas: HTMLCanvasElement | OffscreenCanvas | null = null;
  private _glContext: BackendContext | null = null;
  private retainCount = 0;

  public constructor(canvas: HTMLCanvasElement | OffscreenCanvas, contextAttributes?: WebGLContextAttributes) {
    this._canvas = canvas;
    const gl = canvas.getContext('webgl', {
      ...WEBGL_CONTEXT_ATTRIBUTES,
      ...contextAttributes,
    }) as WebGLRenderingContext;
    if (!gl) throw new Error('Canvas context is not WebGL!');
    this._glContext = BackendContext.from(gl);
  }

  public retain() {
    this.retainCount += 1;
  }

  public release() {
    this.retainCount -= 1;
    if (this.retainCount === 0) {
      if (!this._glContext) return;
      this._glContext.destroy();
      this._glContext = null;
      this._canvas = null;
    }
  }

  public get canvas() {
    return this._canvas;
  }

  public get glContext() {
    return this._glContext;
  }
}
