import { assert } from "../../assert.js";
import { max2 } from "../../math/max2.js";
import { min2 } from "../../math/min2.js";
import { string_repeat } from "../../primitives/strings/string_repeat.js";

class ParserError extends Error {
    /**
     *
     * @param {number} position
     * @param {string} message
     * @param {string} input
     */
    constructor(
        position,
        message,
        input
    ) {

        super();

        assert.isNonNegativeInteger(position, 'position');
        assert.isString(message, 'message');
        assert.isString(input, 'input');

        this.position = position;
        this.message = message;
        this.input = input;
    }

    getDetails() {
        const input = this.input;
        const position = this.position;

        // get snippet around where the problem has occurred
        const input_start = max2(0, position - 10);

        const input_end = min2(input.length, position + 10);

        const snippet = input.slice(input_start, input_end);

        const offset_into_snippet = position - input_start;

        // a piece of text with marker to show where the error occurs
        const arrow_text = string_repeat(" ", offset_into_snippet) + "^"

        return snippet + "\n" + arrow_text;
    }

    toString() {
        return `[ParseError] ${this.message}. Error at position ${this.position} near:\n${this.getDetails()}`
    }
}

export default ParserError;
