import { Application, Container } from 'pixi.js';

/**
 * Рендерер: виртуальное «пиксельное» разрешение, растянутое целым числом на экран
 * с image-rendering: pixelated — это и есть pixel-perfect для пиксель-арта.
 */
export interface RendererOptions {
    /** Виртуальная ширина (например 480). */
    virtualWidth: number;
    /** Виртуальная высота (например 270). */
    virtualHeight: number;
    /** Целочисленный множитель масштаба. */
    scale: number;
    /** Цвет фона. */
    background: number;
    /** Родительский элемент для канваса. */
    parent: HTMLElement;
}

export class Renderer {
    readonly app: Application;
    /** Корневой контейнер мира (к нему применяется камера). */
    readonly worldRoot: Container;
    /** Контейнер UI поверх мира (камерой не двигается). */
    readonly uiRoot: Container;

    readonly virtualWidth: number;
    readonly virtualHeight: number;
    readonly scale: number;

    private readonly parentEl: HTMLElement;

    constructor(options: RendererOptions) {
        this.virtualWidth = options.virtualWidth;
        this.virtualHeight = options.virtualHeight;
        this.scale = options.scale;
        this.parentEl = options.parent;

        this.app = new Application();
        void this.app.init({
            width: options.virtualWidth,
            height: options.virtualHeight,
            backgroundColor: options.background,
            antialias: false,
            roundPixels: true,
            autoStart: false,
            sharedTicker: false
        });

        this.worldRoot = new Container();
        this.uiRoot = new Container();
    }

    /** Дождаться инициализации WebGL и добавить канвас на страницу. */
    async setup(): Promise<void> {
        await this.app.renderer.init;
        this.app.stage.addChild(this.worldRoot, this.uiRoot);

        const canvas = this.app.canvas;
        canvas.style.imageRendering = 'pixelated';
        canvas.style.width = `${this.virtualWidth * this.scale}px`;
        canvas.style.height = `${this.virtualHeight * this.scale}px`;
        this.parentEl.appendChild(canvas);
    }

    /** Рендер кадра (вызывается игровым циклом). */
    render(): void {
        this.app.renderer.render(this.app.stage);
    }
}