"""Contains a configuration parser and project config singleton"""
from configparser import ConfigParser
import json
from pathlib import Path
from typing import Any, FrozenSet, List

from .util import get_git_top_level_path


class Config:
    """ns-poet configuration parser

    Configuration is based on a .ns-poet.cfg file.

    The schema for the file in the git project root is::

        [project]
        ignore_dirs = []
        ignore_targets = []
        python_package_name_prefix = ""
        top_dirs = ["."]

    The schema for the file in an individual python package is::

        [package]
        default_python_runtime = "python3.6"|"python3.7"|...

    Instantiating this class will load and initialize a config parser instance.
    """

    def __init__(self, config_dir_path: Path) -> None:
        """Initialize a config object

        Args:
            config_dir_path: path to a folder containing .ns-poet.cfg file

        """
        self.config_dir_path = config_dir_path
        self._poet_cfg_path = Path(config_dir_path).joinpath(".ns-poet.cfg")
        self._config = ConfigParser()
        self._config["project"] = {}
        self._config["package"] = {}
        if self._poet_cfg_path.is_file():
            self._config.read(self._poet_cfg_path)

    def set(self, *args: Any) -> None:
        """Proxy method to set a value on the underlying config parser instance"""
        self._config.set(*args)

    # Project options

    @property
    def ignore_dirs(self) -> FrozenSet[Any]:
        """Never look for or process files in these directories"""
        return frozenset(
            json.loads(self._config.get("project", "ignore_dirs", fallback="[]"))
        )

    @property
    def ignore_targets(self) -> FrozenSet[Any]:
        """Set of target package names to ignore when collecting build targets"""
        return frozenset(
            json.loads(self._config.get("project", "ignore_targets", fallback="[]"))
        )

    @property
    def python_package_name_prefix(self) -> str:
        """Prefix to use for names of packages generated by ns-poet"""
        return self._config.get("project", "python_package_name_prefix", fallback="")

    @property
    def top_dirs(self) -> List[str]:
        """Top-level directories to search for Python packages"""
        return json.loads(self._config.get("project", "top_dirs", fallback="['.']"))

    # Package options

    @property
    def default_python_runtime(self) -> str:
        """Default python runtime"""
        return self._config.get(
            "package", "default_python_runtime", fallback="python3.6"
        )


# Create a singleton for the project configuration
PROJECT_CONFIG = Config(get_git_top_level_path())
