# master.py
#
# Copyright Uberware. All Rights Reserved

"""Manage the Master."""

import json
import logging
import typing
from collections import namedtuple
from uuid import UUID

from .component import run_component
from .config import SMEDGE

# Use Python standard logging
logger = logging.getLogger("smedge")


MASTER = SMEDGE / "ConfigureMaster"
"""Location of the ConfigureMaster executable, uses config.SMEDGE by default"""


PathTranslation = namedtuple("PathTranslation", ["windows", "linux", "mac"])
"""A simple object that represents the roots used for path translation"""


TranslationType = typing.Union[PathTranslation, list, tuple]
"""A type used for a path translation"""


TranslationListType = typing.Union[TranslationType, typing.List[TranslationType]]
"""A type for input of path translations as either a single item or a list"""


def get_master_id() -> typing.Optional[UUID]:
    """Get the Master's ID"""
    try:
        cmd = [MASTER, "-GetMasterID"]
        result = run_component(cmd)
        if result.stdout.startswith("MasterID: "):
            return UUID(result.stdout[-36:])
    except RuntimeError:
        pass


def get_path_translations() -> typing.List[PathTranslation]:
    """Get the current list of path translations

    Returns:
        A list of PathTranslation objects (which may be empty)

    Raises:
        SmedgeComponentError: Something went wrong
    """
    cmd = [MASTER, "-GetPathTranslations", "-JSON"]
    result = run_component(cmd)
    translations = json.loads(result.stdout)
    return [PathTranslation(win, lin, mac) for win, lin, mac in translations]


def add_path_translations(translations: TranslationListType):
    """Add path translations

    Each translation entry must include all three supported platforms.

    Arguments:
        translations: A translation object or list of translation objects

    Raises:
        TypeError: the translations list is the wrong type
        SmedgeComponentError: Something went wrong
    """
    cmd = []
    if not isinstance(translations, typing.Sequence):
        raise TypeError(
            f"Path translations must be a sequence (got {type(translations)})"
        )
    for element in translations:
        cmd.append("-PathTranslation")
        if isinstance(element, str):
            if len(translations) != 3:
                raise TypeError(
                    f"Translations must have 3 elements (got {len(translations)})"
                )
            cmd.extend(translations)
            break
        elif not isinstance(element, typing.Sequence):
            raise TypeError(
                f"Path translations must be a sequence (got {type(translations)})"
            )
        elif len(element) != 3:
            raise TypeError(
                f"Translations must have 3 elements (got {len(translations)})"
            )
        else:
            cmd.extend(element)
    if cmd:
        run_component([MASTER] + cmd)


def remove_path_translations(roots: typing.Union[str, typing.List[str]]):
    """Remove path translations

    Note that you only need to supply one of the roots of the translation
    to remove the entire entry. Any root works, and if the root matches
    more than one translation set, all of them will be removed.

    Arguments:
        roots: One root or a list of roots.

    Raises:
        TypeError: the translations list is the wrong type
        SmedgeComponentError: Something went wrong
    """
    cmd = []
    if isinstance(roots, str):
        roots = [roots]
    if not isinstance(roots, typing.Sequence):
        raise TypeError(f"Root must be a string or sequence (got {type(roots)})")
    for root in roots:
        if not isinstance(root, str):
            raise TypeError(f"Roots must be strings (got {type(root)})")
        cmd.extend(["-RemovePathTranslation", root])
    if cmd:
        run_component([MASTER] + cmd)


def super_exit():
    """Will attempt to shut down Smedge on the entire network"""
    run_component([MASTER, "-SuperExit"])
