"""Handle Arch for underlay maschine/platforms."""
import logging
from pathlib import Path
import platform
from typing import List

from .coresys import CoreSys, CoreSysAttributes
from .exceptions import HassioArchNotFound, JsonFileError
from .utils.json import read_json_file

_LOGGER = logging.getLogger(__name__)

MAP_CPU = {
    "armv7": "armv7",
    "armv6": "armhf",
    "armv8": "aarch64",
    "aarch64": "aarch64",
    "i686": "i386",
    "x86_64": "amd64",
}


class CpuArch(CoreSysAttributes):
    """Manage available architectures."""

    def __init__(self, coresys: CoreSys) -> None:
        """Initialize CPU Architecture handler."""
        self.coresys = coresys
        self._supported_arch: List[str] = []
        self._default_arch: str

    @property
    def default(self) -> str:
        """Return system default arch."""
        return self._default_arch

    @property
    def supervisor(self) -> str:
        """Return supervisor arch."""
        return self.sys_supervisor.arch

    @property
    def supported(self) -> List[str]:
        """Return support arch by CPU/Machine."""
        return self._supported_arch

    async def load(self) -> None:
        """Load data and initialize default arch."""
        try:
            arch_data = read_json_file(Path(__file__).parent.joinpath("arch.json"))
        except JsonFileError:
            _LOGGER.warning("Can't read arch json")
            return

        native_support = self.detect_cpu()

        # Evaluate current CPU/Platform
        if not self.sys_machine or self.sys_machine not in arch_data:
            _LOGGER.warning("Can't detect underlay machine type!")
            self._default_arch = native_support
            self._supported_arch.append(self.default)
            return

        # Use configs from arch.json
        self._supported_arch.extend(arch_data[self.sys_machine])
        self._default_arch = self.supported[0]

        # Make sure native support is in supported list
        if native_support not in self._supported_arch:
            self._supported_arch.append(native_support)

    def is_supported(self, arch_list: List[str]) -> bool:
        """Return True if there is a supported arch by this platform."""
        return not set(self.supported).isdisjoint(set(arch_list))

    def match(self, arch_list: List[str]) -> str:
        """Return best match for this CPU/Platform."""
        for self_arch in self.supported:
            if self_arch in arch_list:
                return self_arch
        raise HassioArchNotFound()

    def detect_cpu(self) -> str:
        """Return the arch type of local CPU."""
        cpu = platform.machine()
        for check, value in MAP_CPU.items():
            if cpu.startswith(check):
                return value
        return self.sys_supervisor.arch
