import { Component, World } from "@common/rpg/core/world";
import { component } from "@common/rpg/utils/decorators";
import { getPosition, Position } from "../position";
import type { Point } from "@common/geometry";

export interface ViewportData {
    screenX: number;
    screenY: number;
    width: number;
    height: number;
    worldX: number;
    worldY: number;
}

@component
export class Viewport extends Component<void> {
    get screenX(): number {
        return Math.round(getPosition(this.entity, 'screen')?.x ?? 0);
    }

    get screenY(): number {
        return Math.round(getPosition(this.entity, 'screen')?.y ?? 0);
    }

    get width(): number {
        return Math.round(getPosition(this.entity, 'size')?.x ?? Infinity);
    }

    get height(): number {
        return Math.round(getPosition(this.entity, 'size')?.y ?? Infinity);
    }

    get worldX(): number {
        return Math.round(getPosition(this.entity)?.x ?? 0);
    }

    get worldY(): number {
        return Math.round(getPosition(this.entity)?.y ?? 0);
    }

    screenToWorld = ({ x, y }: Point): Point => {
        return {
            x: x - this.screenX + this.worldX,
            y: y - this.screenY + this.worldY,
        };
    }

    worldToScreen = ({ x, y }: Point): Point => {
        return {
            x: x - this.worldX + this.screenX,
            y: y - this.worldY + this.screenY,
        };
    }
}

export const createViewport = (world: World, viewportData: ViewportData) => {
    const viewport = world.createEntity();
    viewport.add(new Viewport());
    viewport.add(new Position(viewportData.worldX, viewportData.worldY));
    viewport.add(new Position(viewportData.width, viewportData.height), 'size');
    viewport.add(new Position(viewportData.screenX, viewportData.screenY), 'screen');

    return viewport;
}
