import { SourceReader } from './reader';
import { i18n } from './i18n';

/* Base class for signalling conditions */
export class GbsInterpreterException extends Error {
    public isGobstonesException: boolean;
    public startPos: SourceReader;
    public endPos: SourceReader;
    public reason: string;
    public args: any[];

    /* Note: position should typically be an instance of SourceReader */
    public constructor(
        startPos: SourceReader,
        endPos: SourceReader,
        errorType: string,
        reason: string,
        args: any[]
    ) {
        super(reason);
        this.isGobstonesException = true;
        this.startPos = startPos;
        this.endPos = endPos;
        this.reason = reason;
        this.args = args;

        const errmsg = i18n(errorType + ':' + reason);
        const msg =
            typeof errmsg === 'string' || errmsg === undefined
                ? errmsg
                : // eslint-disable-next-line @typescript-eslint/ban-types
                  (errmsg as Function)(...args);
        this.message = reason === 'boom-called' ? args[0] : msg;
    }
}

export class GbsWarning extends GbsInterpreterException {
    public constructor(startPos: SourceReader, endPos: SourceReader, reason: string, args: any[]) {
        super(startPos, endPos, 'warning', reason, args);
    }
}

export class GbsSyntaxError extends GbsInterpreterException {
    public constructor(startPos: SourceReader, endPos: SourceReader, reason: string, args: any[]) {
        super(startPos, endPos, 'errmsg', reason, args);
    }
}

export class GbsRuntimeError extends GbsInterpreterException {
    public constructor(startPos: SourceReader, endPos: SourceReader, reason: string, args: any[]) {
        super(startPos, endPos, 'errmsg', reason, args);
    }
}
