import { Container, Assets, Texture, Sprite, Rectangle } from 'pixi';

export default class GameBoard extends Container
{
    constructor(onSlotClickListener)
    {
        super({
            isRenderGroup: true
        });

        this.onSlotClickListener = onSlotClickListener;
    }

    async init()
    {
        const texture = await Assets.load('assets/images/game/board.png');
        const board = new Sprite(texture);
        this.addChild(board);

        // Center pivot point
        this.pivot.x = this.width / 2;
        this.pivot.y = this.height / 2;

        await GameBoardSlot.loadTextures();

        this.initBoard();
    }

    initBoard()
    {
        // We use a two-dimensional array with 4x4 entries, so we can have 1-based indexes for the board
        this.slots = [[],[],[],[]];

        const slotSize = this.width / 3;

        for (let r = 1; r <= 3; r++)
        {
            for (let c = 1; c <= 3; c++)
            {
                const slot = new GameBoardSlot(this.onSlotClickListener);
                slot.position.set((slotSize * (c - 1)) + (slotSize / 2), (slotSize * (r - 1)) + (slotSize / 2));
                this.addChild(slot);

                this.slots[r][c] = slot;

                // Enable slot click
                slot.interactive = true;
                slot.buttonMode = true;
                slot.cursor = 'pointer';

                slot.on('pointerdown', () => {
                    if (this.isEnabled)
                        this.onSlotClickListener(r, c);
                });
            }
        }
    }

    get isEnabled()
    {
        return this._isEnabled;
    }

    set isEnabled(value)
    {
        this._isEnabled = value;
    }

    reset()
    {
        for (let r = 1; r <= 3; r++)
        {
            for (let c = 1; c <= 3; c++)
            {
                const slot = this.slots[r][c];
                slot.setMark(GameBoardSlot.Marks.EMPTY);
            }
        }
    }

    setMark(r, c, value)
    {
        this.slots[r][c].setMark(value);
    }
}

class GameBoardSlot extends Sprite
{
    static Marks = Object.freeze({
        EMPTY: 0,
        CROSS: 1,
        RING: 2,
    });

    constructor()
    {
        super();

        this.setMark(GameBoardSlot.Marks.EMPTY);

        // Center pivot point
        this.pivot.x = this.width / 2;
        this.pivot.y = this.height / 2;
    }

    static async loadTextures()
    {
        GameBoardSlot.textures = [];

        // Load texture atlas image for marks
        const spritesheet = await Assets.load('assets/images/game/marks.png');

        // Define the rectangles for each texture within the image
        GameBoardSlot.textures[GameBoardSlot.Marks.EMPTY] = new Texture({
            source: spritesheet.source,
            frame: new Rectangle(0, 0, 230, 230)
        });
        
        GameBoardSlot.textures[GameBoardSlot.Marks.CROSS] = new Texture({
            source: spritesheet.source,
            frame: new Rectangle(230, 0, 230, 230)
        });
        
        GameBoardSlot.textures[GameBoardSlot.Marks.RING] = new Texture({
            source: spritesheet.source,
            frame: new Rectangle(460, 0, 230, 230)
        });
    }

    setMark(value)
    {
        this.texture = GameBoardSlot.textures[value];

        if (value == GameBoardSlot.Marks.EMPTY)
            this.rotation = 0;
        else
        {
            // Set random rotation
            const randomNumber = Math.floor(Math.random() * 4);
            this.angle = randomNumber * 90;
        }
    }
}