from TexSoup import TexSoup, TexNode
from pathlib import Path


class Parser():
    def __init__(self) -> None:
        pass

    def parse(self, input_path: str, strict_mode: bool) -> TexNode:
        """Parses a TeX file from `input_path` and returns a TexNode object.

        Args:
            input_path (str): Path to the file or to its parent folder.
            strict_mode (bool): If true then input must be valid TeX syntax.

        Returns:
            TexNode: _description_
        """
        path = self._get_input_path(input_path)
        code = self._read(path)
        return TexSoup(code, tolerance=int(not strict_mode))

    def _read(self, path: Path) -> str:
        """Reads a file

        Args:
            path (Path): Path to the file

        Returns:
            str: Contents of the file
        """
        with open(path, 'r') as f:
            return f.read()

    def _get_input_path(self, input_path: str | Path) -> Path:
        """Attempts to get the path to the .tex file. Accepts a path to the 
        file or to its parent folder.

        Args:
            input_path (_type_): Path to the file or parent folder

        Raises:
            FileNotFoundError: If the path does not exist
            ValueError: If the file is not .tex.

        Returns:
            Path: Path to the .tex file
        """
        path = Path(input_path)
        if not path.exists():
            raise FileNotFoundError("Input path does not exist.")
        elif path.is_file():
            if path.suffix == '.tex':
                return path
            else:
                raise ValueError("Input file should be .tex")
        elif path.is_dir():
            return self._get_path_from_dir(path)
        else:
            raise ValueError("Invalid input")

    def _get_path_from_dir(self, folder: Path) -> Path:
        """Looks for a unique .tex file within the directory and returns its
        path.

        Args:
            folder (Path): Parent folder of the .tex file

        Raises:
            ValueError: If there are multiple or no .tex files in the folder.

        Returns:
            Path: Path to the .tex file if it exists.
        """
        def valid_tex(path): return path.is_file() and path.suffix == '.tex'
        files = [f for f in folder.iterdir() if valid_tex(f)]
        if not files:
            raise ValueError(
                "Could not find a valid .tex file within the directory.")
        elif len(files) > 1:
            names = [f.name for f in files]
            raise ValueError(
                f"Multiple .tex files detected {names}. Specify which to use.")
        else:
            return files[0]
