import { Container, Graphics, Rectangle } from 'pixi.js';

/**
 * Виртуальный джойстик для тач-устройств: рисуется в uiRoot, показывает
 * базовый круг и ручку. Игра читает getVector() и двигает персонажа.
 * Появляется там, где игрок коснулся экрана (полупрозрачно), исчезает при отпускании.
 */
export interface VirtualJoystickOptions {
    /** Радиус базового круга (виртуальные пиксели). */
    radius?: number;
    /** Цвета. */
    color?: number;
    /** Отступ от краёв экрана, за который джойстик не заходит. */
    margin?: number;
    /** Полные размеры экрана (виртуальные), чтобы клэмпить позицию. */
    screen: { width: number; height: number };
}

export class VirtualJoystick extends Container {
    private base: Graphics;
    private knob: Graphics;
    private radius: number;
    private margin: number;
    private screen: { width: number; height: number };
    private color: number;
    private dragging = false;

    /** Текущий вектор (-1..1 по каждой оси; длина ≤ 1). */
    private vector = { x: 0, y: 0 };

    constructor(options: VirtualJoystickOptions) {
        super();
        this.radius = options.radius ?? 28;
        this.margin = options.margin ?? 12;
        this.screen = options.screen;
        this.color = options.color ?? 0x8899aa;

        this.visible = false;
        this.eventMode = 'static';
        this.hitArea = new Rectangle(0, 0, this.screen.width, this.screen.height);

        this.base = new Graphics();
        this.knob = new Graphics();
        this.addChild(this.base, this.knob);
        this.drawStatic();

        this.on('pointerdown', (e) => this.onDown(e.global.x, e.global.y));
        this.on('pointermove', (e) => {
            if (this.dragging) this.onMove(e.global.x, e.global.y);
        });
        this.on('pointerup', () => this.release());
        this.on('pointerupoutside', () => this.release());
    }

    /** Вектор управления; активен ли джойстик сейчас. */
    getVector(): { x: number; y: number } {
        return { x: this.vector.x, y: this.vector.y };
    }

    get active(): boolean {
        return this.dragging;
    }

    /** Обновить размеры экрана (при ресайзе). */
    setScreen(width: number, height: number): void {
        this.screen = { width, height };
    }

    private onDown(px: number, py: number): void {
        this.dragging = true;
        this.visible = true;
        this.reposition(px, py);
        this.updateKnob(px, py);
    }

    private onMove(px: number, py: number): void {
        this.updateKnob(px, py);
    }

    private release(): void {
        this.dragging = false;
        this.visible = false;
        this.vector = { x: 0, y: 0 };
    }

    private reposition(px: number, py: number): void {
        const x = Math.min(Math.max(px, this.margin + this.radius), this.screen.width - this.margin - this.radius);
        const y = Math.min(Math.max(py, this.margin + this.radius), this.screen.height - this.margin - this.radius);
        this.position.set(x, y);
    }

    private updateKnob(px: number, py: number): void {
        let dx = px - this.x;
        let dy = py - this.y;
        const len = Math.hypot(dx, dy);
        const max = this.radius;
        if (len > max) {
            dx = (dx / len) * max;
            dy = (dy / len) * max;
        }
        this.knob.position.set(dx, dy);
        this.vector = { x: dx / max, y: dy / max };
    }

    private drawStatic(): void {
        this.base.clear();
        this.base.circle(0, 0, this.radius).stroke({ color: this.color, width: 1, alpha: 0.5 });
        this.base.circle(0, 0, this.radius * 0.6).fill({ color: this.color, alpha: 0.08 });
        this.knob.clear();
        this.knob.circle(0, 0, this.radius * 0.35).fill({ color: this.color, alpha: 0.6 });
    }
}