import tomllib

from functools import cached_property
from pathlib import Path

from wox.constants import DOT_WOX
from wox.utils import rmtree_with_retry
from wox.wox_exceptions import ConfigFileNotFoundError, MissingWoxSectionError


class WoxSteward():
    """
        Manages the woxspace (.wox) and handles the settings written in
        the .toml file.

        Attributes
        ----------
        dot_wox : pathlib.Path
            Path to .wox directory.
        wox_toml : pathlib.Path
            Path to configuration file.
        wox_data : dict
            Data extracted from configuration files.
    """

    def __init__(self):
        self.dot_wox = DOT_WOX


    @cached_property
    def wox_toml(self):
        """
            Locates the configuration file.

            Returns
            -------
            pathlib.Path
                Path to config file.

            Raises
            ------
            ConfigFileNotFoundError
                No config file found at root of workspace.
        """

        toml_file_names = ['wox', 'pyproject']

        for name in toml_file_names:
            wox_toml = Path.cwd() / f'{name}.toml'
            if wox_toml.exists():
                return wox_toml

        raise ConfigFileNotFoundError

    @cached_property
    def wox_data(self):
        """
            Data extraction from configuration file.

            Returns
            -------
            dict
                Wox data from config file.

            Raises
            ------
            MissingWoxSectionError
                Wox section in pyproject.toml not found.
        """

        with open(self.wox_toml, 'rb') as toml_file:
            data = tomllib.load(toml_file)

        match self.wox_toml.name:
            case 'pyproject.toml':
                try:
                    wox_data = data['tool']['wox']
                except KeyError:
                    raise MissingWoxSectionError
            case 'wox.toml':
                wox_data = data

        return wox_data

    def dot_wox_setup(self):
        """
            Sets up the woxspace in the .wox directory.
        """

        gitignore = self.dot_wox / '.gitignore'

        if not gitignore.exists():
            with open(f'{gitignore}', 'w', encoding = 'utf-8') as file:
                file.write('# Automatically created by wox.\n')
                file.write('*\n')

        cachedir_tag = self.dot_wox / 'CACHEDIR.TAG'

        if not cachedir_tag.exists():
            cachedir_tag.write_text(
                'Signature: 8a477f597d28d172789f06886806bc55\n'
                '# This directory is managed by Wox.\n'
                '# It contains cache data such as logs and virtual environments.\n'
                '# See: https://bford.info/cachedir/\n'
            )

    def purge_wox(self):
        """
            Deletes all directories and files in .wox except .logs and recreates
            .gitignore and CACHEDIR.TAG.
        """

        for element in self.dot_wox.iterdir():
            if element.name == '.logs':
                continue

            if element.is_dir():
                rmtree_with_retry(element)
            else:
                element.unlink()

        self.dot_wox_setup()
