package p.studio.compiler.pbs.parser;

import p.studio.compiler.pbs.ast.PbsAst;
import p.studio.compiler.pbs.lexer.PbsToken;
import p.studio.compiler.pbs.lexer.PbsTokenKind;
import p.studio.compiler.source.Span;

final class PbsExprParserContext {
    private final PbsParserContext parserContext;
    private final PbsTokenCursor cursor;
    private final PbsExprParser.BlockParserDelegate blockParserDelegate;

    PbsExprParserContext(
            final PbsParserContext parserContext,
            final PbsExprParser.BlockParserDelegate blockParserDelegate) {
        this.parserContext = parserContext;
        this.cursor = parserContext.cursor();
        this.blockParserDelegate = blockParserDelegate;
    }

    PbsTokenCursor cursor() {
        return cursor;
    }

    PbsAst.Block parseSurfaceBlock(final String message) {
        return blockParserDelegate.parse(message);
    }

    PbsToken consume(final PbsTokenKind kind, final String message) {
        if (cursor.check(kind)) {
            return cursor.advance();
        }
        final var token = cursor.peek();
        report(token, ParseErrors.E_PARSE_EXPECTED_TOKEN, message + ", found " + token.kind());
        if (!cursor.isAtEnd()) {
            return cursor.advance();
        }
        return token;
    }

    PbsToken consumeMemberName(final String message) {
        if (cursor.check(PbsTokenKind.IDENTIFIER)) {
            return cursor.advance();
        }
        final var token = cursor.peek();
        report(token, ParseErrors.E_PARSE_EXPECTED_TOKEN, message + ", found " + token.kind());
        if (!cursor.isAtEnd()) {
            return cursor.advance();
        }
        return token;
    }

    Span span(final long start, final long end) {
        return parserContext.span(start, end);
    }

    void report(final PbsToken token, final ParseErrors parseErrors, final String message) {
        parserContext.report(token, parseErrors, message);
    }
}
