package p.studio.compiler.pbs.semantics;

import p.studio.compiler.pbs.ast.PbsAst;

final class PbsCtorReturnScanner {
    private PbsCtorReturnScanner() {
    }

    static boolean containsReturnStatement(final PbsAst.Block block) {
        if (block == null) {
            return false;
        }

        for (final var statement : block.statements()) {
            if (statement instanceof PbsAst.ReturnStatement) {
                return true;
            }
            if (statement instanceof PbsAst.IfStatement ifStatement) {
                if (containsReturnInIfStatement(ifStatement)) {
                    return true;
                }
                continue;
            }
            if (statement instanceof PbsAst.ForStatement forStatement && containsReturnStatement(forStatement.body())) {
                return true;
            }
            if (statement instanceof PbsAst.WhileStatement whileStatement && containsReturnStatement(whileStatement.body())) {
                return true;
            }
            if (statement instanceof PbsAst.ExpressionStatement expressionStatement && containsReturnExpression(expressionStatement.expression())) {
                return true;
            }
        }

        return block.tailExpression() != null && containsReturnExpression(block.tailExpression());
    }

    private static boolean containsReturnInIfStatement(final PbsAst.IfStatement ifStatement) {
        if (ifStatement == null) {
            return false;
        }
        if (containsReturnStatement(ifStatement.thenBlock()) || containsReturnStatement(ifStatement.elseBlock())) {
            return true;
        }
        return containsReturnInIfStatement(ifStatement.elseIf());
    }

    private static boolean containsReturnExpression(final PbsAst.Expression expression) {
        if (expression == null) {
            return false;
        }
        if (expression instanceof PbsAst.BlockExpr blockExpr) {
            return containsReturnStatement(blockExpr.block());
        }
        if (expression instanceof PbsAst.IfExpr ifExpr) {
            return containsReturnStatement(ifExpr.thenBlock()) || containsReturnExpression(ifExpr.elseExpression());
        }
        if (expression instanceof PbsAst.SwitchExpr switchExpr) {
            for (final var arm : switchExpr.arms()) {
                if (containsReturnStatement(arm.block())) {
                    return true;
                }
            }
        }
        if (expression instanceof PbsAst.HandleExpr handleExpr) {
            for (final var arm : handleExpr.arms()) {
                if (containsReturnStatement(arm.block())) {
                    return true;
                }
            }
        }
        return false;
    }
}
