import { Application, Container } from 'pixi.js';
import { setPixelTextResolution } from '../ui/PixelText';

/**
 * Рендерер: виртуальное «пиксельное» разрешение. CSS-размер канваса — виртуальное
 * разрешение, растянутое целым числом (image-rendering: pixelated); бэкинг-стор —
 * в пикселях устройства (scale × dpr), поэтому UI и текст резкие, а мир остаётся
 * пиксельным (текстуры мира сэмплируются nearest — см. AssetLoader).
 */
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;
    private _scale: number;

    /** Текущий целочисленный масштаб. */
    get scale(): number {
        return this._scale;
    }

    private readonly parentEl: HTMLElement;
    private readonly initPromise: Promise<void>;

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

        this.app = new Application();
        this.initPromise = 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.initPromise;
        this.app.stage.addChild(this.worldRoot, this.uiRoot);

        const canvas = this.app.canvas;
        canvas.style.imageRendering = 'pixelated';
        this.applySize();
        this.parentEl.appendChild(canvas);
    }

    /**
     * Сменить целочисленный масштаб (обычно при ресайзе окна).
     * Виртуальное разрешение не меняется — меняется только CSS-размер канваса.
     */
    resize(scale: number): void {
        this._scale = Math.max(1, Math.floor(scale));
        this.applySize();
    }

    private applySize(): void {
        const canvas = this.app.canvas;
        // Бэкинг-стор — в пикселях устройства: UI и текст рендерятся 1:1 с экраном.
        const dpr = window.devicePixelRatio || 1;
        const resolution = Math.max(1, Math.round(this._scale * dpr));
        if (this.app.renderer.resolution !== resolution) {
            this.app.renderer.resolution = resolution;
            this.app.renderer.resize(this.virtualWidth, this.virtualHeight);
            setPixelTextResolution(resolution);
        }
        canvas.style.width = `${this.virtualWidth * this._scale}px`;
        canvas.style.height = `${this.virtualHeight * this._scale}px`;
    }

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