import { Graphics, Rectangle } from 'pixi.js';
import BaseMachine from '../slotMachines/BaseMachine';
import BaseSystem from './BaseSystem';

export interface InteractiveGridSystemSettings
{
    debug: boolean;
}

export type InteractiveGridSystemEventData = {
    reel: number;
    slot: number;
    mapIndex: number;
};

export default class InteractiveGridSystem extends BaseSystem<InteractiveGridSystemSettings>
{
    static defaultSettings: InteractiveGridSystemSettings = {
        debug: false,
    };

    static override requiredFlags: string[] = [];
    static override requiredMaps: string[] = [];
    static override requiredInputs: string[] = [];
    static override requiredMethods: string[] = [];
    static override requiredUtils: string[] = ['grid'];
    static override sharedSystemData: string[] = [];

    public state: string = 'stopped';
    private debugGraphics: Graphics;
    private pressedSlot: {reel: number; slot: number};
    private isSlotPressed: boolean = false;
    private prevIsSlotPressed: boolean = false;

    constructor(machine: BaseMachine)
    {
        super(machine);
        this.setSettings(InteractiveGridSystem.defaultSettings);
        this.machine.eventMode = 'static';
        this.createHitArea();
        this.createGrid();
    }

    onEnter(): void
    {
        this.machine.on('pointerdown', this.handlePointerDown, this);
        this.machine.on('pointerup', this.handlePointerUp, this);
    }

    onLeave(): void
    {
        this.machine.off('pointerdown', this.handlePointerDown, this);
        this.machine.off('pointerup', this.handlePointerUp, this);
    }

    update(_dt: number): void
    {
        this.debugGraphics.visible = this.settings.debug;
        if (this.debugGraphics.visible) this.updateDebugGraphics();

        if (this.isSlotPressed && !this.prevIsSlotPressed)
        {
            this.machine.events.addEvent('slotPressed', this.pressedSlot);
        }
        else if (this.prevIsSlotPressed && !this.isSlotPressed)
        {
            this.machine.events.addEvent('slotReleased', this.pressedSlot);
            this.pressedSlot = undefined;
        }
        this.prevIsSlotPressed = this.isSlotPressed;
    }

    handlePointerDown(e: any): void
    {
        const position = this.machine.toLocal(e.global);
        const w = this.machine.utils.grid.getSlotWidth();
        const h = this.machine.utils.grid.getSlotHeight();
        const reel = Math.floor(position.x / w);
        const slot = Math.floor(position.y / h);
        const mapIndex = this.machine.utils.grid.fromCRtoMapIndex(reel, slot);
        const eventData: InteractiveGridSystemEventData = { reel, slot, mapIndex };

        this.pressedSlot = eventData;
        this.isSlotPressed = true;
    }

    handlePointerUp(_e: any): void
    {
        this.isSlotPressed = false;
    }

    private createGrid()
    {
        const gr = new Graphics();

        this.machine.addChild(gr);
        gr.zIndex = 10000;
        this.debugGraphics = gr;
    }

    private createHitArea()
    {
        const { slots, reels } = this.machine.config;
        const w = this.machine.utils.grid.getSlotWidth();
        const h = this.machine.utils.grid.getSlotHeight();

        this.machine.hitArea = new Rectangle(0, 0, w * reels, h * slots);
    }

    private updateDebugGraphics()
    {
        const w = this.machine.utils.grid.getSlotWidth();
        const h = this.machine.utils.grid.getSlotHeight();

        this.debugGraphics.clear();
        this.debugGraphics.lineStyle(2, 0xff0000);
        const { slots, reels } = this.machine.config;

        for (let i = 0; i < reels; i++)
        {
            for (let j = 0; j < slots; j++)
            {
                const x = i * w;
                const y = j * h;

                this.debugGraphics.drawRect(x, y, w, h);
            }
        }
        if (!this.pressedSlot) return;
        this.debugGraphics.beginFill(0x00ff00, 0.5);
        this.debugGraphics.drawRect(
            this.pressedSlot.reel * w,
            this.pressedSlot.slot * h,
            w,
            h
        );
    }
}
