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

/**
 * Кнопка UI: пиксельная рамка, состояния normal/hover/pressed/focused.
 * Активация — клик мышью или onSelect() из клавиатурной навигации (MenuList).
 */
export interface ButtonOptions {
    label: string;
    width: number;
    height: number;
    size?: number;
    /** Значение справа (громкость, счётчик) — меняется без пересборки списка. */
    value?: string;
    /** Недоступная кнопка: приглушена, клик/активация игнорируются. */
    disabled?: boolean;
    onSelect?: () => void;
}

type ButtonState = 'normal' | 'hover' | 'pressed' | 'focused';

const STATE_COLORS: Record<ButtonState, { fill: number; border: number; text: number }> = {
    normal: { fill: 0x16161f, border: 0x8899aa, text: 0xcccccc },
    hover: { fill: 0x1e1e2a, border: 0xf0d878, text: 0xffffff },
    pressed: { fill: 0x2a2a38, border: 0xf0d878, text: 0xffffff },
    focused: { fill: 0x1e1e2a, border: 0xd99a32, text: 0xffffff }
};

const DISABLED_COLORS = { fill: 0x101018, border: 0x555560, text: 0x777780 };

/** Цвет значения (приглушённый акцент — не путать с меткой). */
const VALUE_COLOR = 0xb8c4cc;

export class Button extends Container {
    readonly labelText: PixelText;
    readonly valueText: PixelText | null = null;
    onSelect: (() => void) | null;

    private bg: Graphics;
    private state: ButtonState = 'normal';
    private readonly w: number;
    private readonly h: number;
    private readonly size: number;
    private readonly disabled: boolean;

    constructor(options: ButtonOptions) {
        super();
        this.w = options.width;
        this.h = options.height;
        this.size = options.size ?? 10;
        this.disabled = options.disabled ?? false;
        this.onSelect = options.onSelect ?? null;

        this.bg = new Graphics();
        // Защита от длинной метки: перенос по ширине кнопки (иначе текст
        // вылезает за рамку; двухстрочная метка в высокой кнопке читаема).
        this.labelText = new PixelText({
            text: options.label,
            size: this.size,
            color: this.disabled ? DISABLED_COLORS.text : STATE_COLORS.normal.text,
            align: options.value !== undefined ? 'left' : 'center',
            wordWrapWidth: this.w - 16
        });
        if (options.value !== undefined) {
            // С value метка прижата влево, значение — к правому краю.
            this.labelText.anchor.set(0, 0.5);
            this.labelText.position.set(8, this.h / 2);
            this.valueText = new PixelText({
                text: options.value,
                size: this.size,
                color: VALUE_COLOR,
                align: 'right'
            });
            this.valueText.anchor.set(1, 0.5);
            this.valueText.position.set(this.w - 8, this.h / 2);
        } else {
            this.labelText.anchor.set(0.5);
            this.labelText.position.set(this.w / 2, this.h / 2);
        }

        this.addChild(this.bg, this.labelText);
        if (this.valueText) this.addChild(this.valueText);

        // Недоступная кнопка прозрачна для ввода (клики проходят сквозь)
        this.eventMode = this.disabled ? 'none' : 'static';
        if (!this.disabled) {
            this.cursor = 'pointer';
            this.hitArea = new Rectangle(0, 0, this.w, this.h);
            this.on('pointerover', () => this.setState(this.state === 'pressed' ? 'pressed' : 'hover'));
            this.on('pointerout', () => this.setState(this.focused ? 'focused' : 'normal'));
            this.on('pointerdown', (e: FederatedPointerEvent) => {
                e.stopPropagation();
                this.setState('pressed');
            });
            this.on('pointerup', () => this.setState('hover'));
            this.on('pointerupoutside', () => this.setState('normal'));
            this.on('pointertap', () => this.onSelect?.());
        }

        this.draw();
    }

    /** Клавиатурный фокус (визуально — рамка акцентного цвета). */
    set focused(value: boolean) {
        if (value && this.state === 'normal') this.setState('focused');
        else if (!value && this.state === 'focused') this.setState('normal');
    }

    get focused(): boolean {
        return this.state === 'focused';
    }

    /** Программная активация (Enter из MenuList). */
    activate(): void {
        if (this.disabled) return;
        this.onSelect?.();
    }

    private setState(s: ButtonState): void {
        this.state = s;
        this.labelText.style.fill = STATE_COLORS[s].text;
        if (this.valueText) this.valueText.style.fill = this.disabled ? DISABLED_COLORS.text : VALUE_COLOR;
        this.draw();
    }

    /** Обновить значение справа (без пересборки списка). */
    set value(v: string) {
        if (this.valueText) this.valueText.text = v;
    }

    private draw(): void {
        const c = this.disabled ? DISABLED_COLORS : STATE_COLORS[this.state];
        this.bg.clear();
        this.bg.rect(0, 0, this.w, this.h).fill({ color: c.fill, alpha: 0.95 });
        this.bg.rect(0, 0, this.w, this.h).stroke({ color: c.border, width: 1 });
    }
}