import time
from datetime import datetime
from os.path import join
from typing import List

from .classes import SpecificEtcdEntryBase


class HostStatus:
    """Possible Statuses of uncloud host."""

    alive = "ALIVE"
    dead = "DEAD"


class HostEntry(SpecificEtcdEntryBase):
    """Represents Host Entry Structure and its supporting methods."""

    def __init__(self, e):
        self.specs = None  # type: dict
        self.hostname = None  # type: str
        self.status = None  # type: str
        self.last_heartbeat = None  # type: str

        super().__init__(e)

    def update_heartbeat(self):
        self.status = HostStatus.alive
        self.last_heartbeat = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")

    def is_alive(self):
        last_heartbeat = datetime.strptime(
            self.last_heartbeat, "%Y-%m-%d %H:%M:%S"
        )
        delta = datetime.utcnow() - last_heartbeat
        if delta.total_seconds() > 60:
            return False
        return True

    def declare_dead(self):
        self.status = HostStatus.dead
        self.last_heartbeat = time.strftime("%Y-%m-%d %H:%M:%S")


class HostPool:
    def __init__(self, etcd_client, host_prefix):
        self.client = etcd_client
        self.prefix = host_prefix

    @property
    def hosts(self) -> List[HostEntry]:
        _hosts = self.client.get_prefix(self.prefix, value_in_json=True)
        return [HostEntry(host) for host in _hosts]

    def get(self, key):
        if not key.startswith(self.prefix):
            key = join(self.prefix, key)
        v = self.client.get(key, value_in_json=True)
        if v:
            return HostEntry(v)
        return None

    def put(self, obj: HostEntry):
        self.client.put(obj.key, obj.value, value_in_json=True)

    def by_status(self, status, _hosts=None):
        if _hosts is None:
            _hosts = self.hosts
        return list(filter(lambda x: x.status == status, _hosts))