import asyncio
import os
from typing import Dict, List, Optional

import aiofiles
from yaml import BaseLoader, load


class ConfigOptionNGCP:
    """Config option NGCP.

    Attributes:
        role (Dict): a set of NGCP roles of the node
            that are either 'yes' or 'no'
        status (str): node status ['online','offline','inactive']
        node_name (str): NGCP node name of the current host

    """
    role: Dict[str, str]
    status: str
    node_name: str
    roles: Dict[str, List[Dict[str, str]]]


class Config:
    """The app's config class.

    If dev mode is enabled, some functionality is changed to accommodate
    the project run in the dev environment

    Attributes:
        app_name (str): app's name, used as the process name
        dev_mode (bool): development mode
        config_file (str): config file
        pid_file (str): app's process pid file
        task_conf_dir (str): directory that contains tasks
        backend_conf_dir (str): directory that contains backends
        ngcp (ConfigOptionNGCP): NGCP node related options

    """

    app_name: str
    dev_mode: bool
    config_file: str
    pid_file: str
    task_conf_dir: str
    backend_conf_dir: str
    ngcp: ConfigOptionNGCP
    systemd_controlled: bool

    def __init__(self) -> None:
        """Config class constructor.

        Args:
            None

        Returns:
            None

        """
        self.app_name = 'ngcp-task-agent'
        self.dev_mode = os.getenv('VIRTUAL_ENV') is not None
        self.config_file = '/etc/ngcp-task-agent/agent.conf'
        self.systemd_controlled = True if os.getppid() == 1 else False

        if self.dev_mode:
            self.config_file = 'etc/agent.conf'

    async def read_config(self) -> None:
        """Reads config.

        Overrides config dir options if dev_mode is enabled

        Args:
            None

        Returns
            None

        """
        async with aiofiles.open(self.config_file, 'r',
                                 loop=asyncio.get_running_loop(),
                                 encoding='utf-8') as file:
            yaml = load(await file.read(), BaseLoader)
            # types are fixed in App.run() after read_config()
            self.__dict__.update(yaml)

        if self.dev_mode:
            self.task_conf_dir = 'etc/tasks'
            self.backend_conf_dir = 'etc/backends'
