/** Immutable collection of slot line definitions. */
export type LineDefinition = number[];
export type LinesConfig = ReadonlyArray<ReadonlyArray<number>>;

const MISSING_LINES_DATA_ERROR = 'Please, provide the Lines with data. use \'Lines.init(your_data)\'';

export default class Lines
{
    private readonly data: LineDefinition[];

    constructor(data: LinesConfig | null | undefined)
    {
        if (!data)
        {
            throw new Error(MISSING_LINES_DATA_ERROR);
        }

        if (!Array.isArray(data))
        {
            throw new Error('Lines data must be an array of line definitions.');
        }

        this.data = data.map((line, lineIndex) =>
        {
            if (!Array.isArray(line))
            {
                throw new Error(`Line ${lineIndex} must be an array of reel positions.`);
            }

            line.forEach((position, columnIndex) =>
            {
                if (!Number.isInteger(position))
                {
                    throw new Error(`Line ${lineIndex} has invalid reel position at column ${columnIndex}.`);
                }
            });

            return [...line];
        });
    }

    /** Returns cloned line definitions. */
    get lines(): LineDefinition[]
    {
        return this.data.map((line) => [...line]);
    }

    /**
     * Returns a cloned line by index.
     * @param lineIndex
     */
    get(lineIndex: number): LineDefinition
    {
        if (!Number.isInteger(lineIndex) || lineIndex < 0 || lineIndex >= this.data.length)
        {
            throw new Error(`There isn't a line with the index ${lineIndex}`);
        }

        return [...this.data[lineIndex]];
    }

    /** Total configured line count. */
    numberOfLines(): number
    {
        return this.data.length;
    }
}
