import { Point } from 'pixi.js';
import { SlotMachineConfig } from '../types/SlotMachineConfig';

/**
 * @class GridUtils
 * @description Utility class for working with slot grid configuration, coordinates, and indices.
 */
export default class GridUtils
{
    private config: SlotMachineConfig;
    private slotWidth: number;
    private slotHeight: number;
    private slotCenter: Point;

    /**
     * @class
     * @param {SlotMachineConfig} config - Configuration for the slot grid.
     */
    constructor(config: SlotMachineConfig)
    {
        this.config = config;
        this.slotWidth = config.width / config.reels;
        this.slotHeight = config.height / config.slots;
        this.slotCenter = new Point(this.slotWidth * 0.5, this.slotHeight * 0.5);
    }

    /**
     * Converts a linear index to the XY coordinates of the slot's center.
     * @param {number} i - The linear index in the grid.
     * @returns {Point | null} The center coordinates of the slot or `null` if the index is out of bounds.
     */
    fromMapIndexToXY(i: number): Point | null
    {
        if (i < 0 || i >= this.config.reels * this.config.slots) return null;
        const x = (this.getColumn(i) * this.slotWidth) + this.slotCenter.x;
        const y = (this.getRow(i) * this.slotHeight) + this.slotCenter.y;

        return new Point(x, y);
    }

    /**
     * Converts a linear index to grid coordinates.
     * @param {number} i - The linear index in the grid.
     * @returns {{ x: number, y: number } | null} The grid coordinates or `null` if the index is out of bounds.
     */
    fromMapIndexToGridCoords(i: number): { x: number; y: number } | null
    {
        if (i < 0 || i >= this.config.reels * this.config.slots) return null;

        return {
            x: this.getColumn(i),
            y: this.getRow(i),
        };
    }

    /**
     * Returns the width of a single slot.
     * @returns {number} The slot width.
     */
    getSlotWidth(): number
    {
        return this.slotWidth;
    }

    /**
     * Returns the height of a single slot.
     * @returns {number} The slot height.
     */
    getSlotHeight(): number
    {
        return this.slotHeight;
    }

    /**
     * Converts column and row coordinates to a linear index.
     * @param {number} c - The column number.
     * @param {number} r - The row number.
     * @returns {number | null} The linear index or `null` if the values are out of bounds.
     */
    fromCRtoMapIndex(c: number, r: number): number | null
    {
        if (c < 0 || c >= this.config.reels || r < 0 || r >= this.config.slots) return null;

        return (r * this.config.reels) + c;
    }

    /**
     * Returns the row for a given index in the grid.
     * @param {number} i - The linear index in the grid.
     * @returns {number} The row number.
     */
    getRow(i: number): number
    {
        return Math.floor(i / this.config.reels);
    }

    /**
     * Returns the column for a given index in the grid.
     * @param {number} i - The linear index in the grid.
     * @returns {number} The column number.
     */
    getColumn(i: number): number
    {
        return i % this.config.reels;
    }
}
