import requests
import time
import typing
import logging

REQUEST_TIMEOUT = 2

LOG = logging.getLogger(__name__)


class Webif(object):
    def __init__(self, ip_address: str, port: int, ssl: bool = False):
        self.webif_ip = ip_address
        self.webif_port = port
        self.use_ssl = ssl

        protocol = 'http' if not ssl else 'https'
        self.base_url = '{}://{}:{}'.format(protocol, self.webif_ip, self.webif_port)

        self.session = requests.session()

    def get_host(self):
        return self.webif_ip

    @property
    def epoch_ms(self) -> int:
        """
        Epoch timestamp in milliseconds
        """
        return int(round(time.time() * 1000))

    def get(
        self, url: str, timeout: int = REQUEST_TIMEOUT, **kwargs
    ) -> typing.Union[requests.Response, None]:
        """
        Wrapper around GET

        Args:
            url: URL to request
            timeout: Timeout in seconds, logs error and returns None if hit

        Returns:
            Response on successful transmission, None on timeout or connection error
        """
        try:
            resp = self.session.get(url, timeout=timeout, **kwargs)
        except requests.exceptions.Timeout:
            LOG.warning('GET to {} timed out'.format(url))
            return None
        except requests.exceptions.ConnectionError:
            LOG.warning('Connection error on attempted GET request')
            return None

        return resp

    def post(
        self, url: str, timeout: int = REQUEST_TIMEOUT, **kwargs
    ) -> typing.Union[requests.Response, None]:
        """
        Wrapper around POST

        Args:
            url: URL to request
            timeout: Timeout in seconds, logs error and returns None if hit

        Returns:
            Response on successful transmission, None on timeout or connection error
        """
        try:
            resp = self.session.post(url, timeout=timeout, **kwargs)
        except requests.exceptions.Timeout:
            LOG.warning('POST to {} timed out'.format(url))
            return None
        except requests.exceptions.ConnectionError:
            LOG.warning('Connection error on attempted POST request')
            return None

        return resp

    def ensure_host_is_up(self) -> bool:
        """
        Ensure host is alive / reachable
        LOG.debug('Host {} is up ;)'.format(self.webif_ip)
        return True
        Returns:
            True if host is up, False otherwise
        """
        ret = self.get(self.base_url)
        if ret is not None:
            LOG.debug('Host {} is up ;)'.format(self.webif_ip))
            return True
        return False
