from builders.maze_builder import MazeBuilder
from core.cell import Cell
from core.maze import Maze


class TextFileMazeBuilder(MazeBuilder):

    def buildFromFile(self, filename):

        with open(filename, "r", encoding="utf-8") as source:
            raw_lines = [line.rstrip("\n") for line in source]

        if not raw_lines:
            raise ValueError("Maze file is empty")

        expected_width = len(raw_lines[0])

        blueprint = []
        start_cell = None
        exit_cell = None

        for y_index, raw in enumerate(raw_lines):

            if len(raw) != expected_width:
                raise ValueError(
                    f"Broken maze shape at line {y_index + 1}"
                )

            row_pack = []

            for x_index, symbol in enumerate(raw):

                current = None

                if symbol == "#":
                    current = Cell(
                        x_index,
                        y_index,
                        isWall=True
                    )

                elif symbol == " ":
                    current = Cell(
                        x_index,
                        y_index
                    )

                elif symbol == "S":

                    if start_cell:
                        raise ValueError(
                            "Multiple start cells detected"
                        )

                    current = Cell(
                        x_index,
                        y_index,
                        isStart=True
                    )

                    start_cell = current

                elif symbol == "E":

                    if exit_cell:
                        raise ValueError(
                            "Multiple exit cells detected"
                        )

                    current = Cell(
                        x_index,
                        y_index,
                        isExit=True
                    )

                    exit_cell = current

                else:
                    raise ValueError(
                        f"Unsupported symbol '{symbol}' "
                        f"at ({x_index}, {y_index})"
                    )

                row_pack.append(current)

            blueprint.append(row_pack)

        if start_cell is None:
            raise ValueError(
                "Start cell S not found"
            )

        if exit_cell is None:
            raise ValueError(
                "Exit cell E not found"
            )

        return Maze(
            blueprint,
            start_cell=start_cell,
            exit_cell=exit_cell
        )