import requests
from http import HTTPStatus
from urllib.parse import urlparse

from anaconda_navigator.utils.logs import logger


class AdvertisementMixin:
    def _is_valid_url(self, url):
        parse_result = urlparse(url)

        if not all((parse_result.scheme, parse_result.netloc, parse_result.path)):
            self.errors.append('{} is not a valid URL'.format(url))
            return False
        return True
    
    def _log_errors(self):
        for error in self.errors:
            logger.error(error)


class AdvertisementsList(AdvertisementMixin):
    BANNER_TIMEOUT_MS = 60000

    def __init__(self, source_url):
        self.source_url = source_url
        self.advertisements = []
        self.errors = []
        self.load()

        self._log_errors()
    
    def load(self):
        """
        Tries to load the data to be displayed in the advertisements.
        """
        try:
            resp = requests.get(self.source_url)

            if resp.status_code == HTTPStatus.OK:
                for data in resp.json():
                    image_url = data.get('image_url')
                    redirect_url = data.get('redirect_url')
                    text = data.get('text')
                    
                    ad = Advertisement(image_url, redirect_url, text)

                    if ad.is_valid():
                        self.advertisements.append(ad)

        except requests.ConnectionError:
            self.errors.append(
                'Tried to load advertisement data from {}. URL is not reachable'.format(self.source_url)
            )
        except Exception as e:
            self.errors.append(
                'Unexpected error while loading advertisement. Stacktrace: {}'.format(str(e))
            )

    def advertisements_carousel(self):
        start_pos = 0
        adlen = len(self.advertisements)
        while start_pos < adlen:
            curr_pos = start_pos
            res = self.advertisements[start_pos]
            start_pos = (start_pos + 1) if start_pos + 1 < adlen else 0
            yield curr_pos, res
        

class Advertisement(AdvertisementMixin):
    """
    Class for loading advertisements data, handling errors and validating data.
    """

    def __init__(self, image_url, redirect_url, text):
        self.errors = []
        self.image = None
        if self._is_valid_url(image_url):
            self.image = self._load_image(image_url)
        
        self.url = None
        if self._is_valid_url(redirect_url):
            self.url = redirect_url

        self.text = text

        self._log_errors()

    def is_valid(self):
        """
        Checks if all needed data is present and correct.
        """
        image_and_link = self.image and self.url
        text_and_link = self.text and self.url
        all_set = self.text and self.url and self.image

        return all_set or image_and_link or text_and_link

    def _load_image(self, image_url):
        """
        Tries to load the image of an advertisement.

        :param str image_url: The url of the image to be downloaded.
        """
        resp = requests.get(image_url)
        
        if resp.status_code == HTTPStatus.OK:
            return resp.content
        else:
            self.errors.append(
                'Tried to load advertisement image from {}. Data is not fetched with status {}'.format(
                    image_url, resp.status_code
                )
            )
