import logging
import requests

from common.models import Job
from django.conf import settings
from requests.exceptions import RequestException, Timeout, ConnectionError
from threading import Thread


logger = logging.getLogger(__name__)


class TankAPICommunicator:
    def __init__(self, job_id):
        job = Job.objects.get(id=job_id)
        self.job = job
        self.host = job.host
        self.port = job.port
        self.local_id = job.local_uuid

        self._configs = None

        self._raw_artifacts_list = None
        self._artifacts_list_thread = Thread(target=self._send_artifacts_list_request)
        self._artifacts_list_thread.start()

    @property
    def address(self):
        return 'http://{}:{}'.format(self.host, self.port)

    def _send_artifacts_list_request(self):
        url = self.address + '/api/v1/tests/{}/logs.json'.format(self.local_id)
        try:
            response = requests.get(url, timeout=settings.ARTIFACTS_LIST_REQUEST_TIMEOUT)
            self._raw_artifacts_list = response.json()
        except (ConnectionError, Timeout, ValueError) as e:
            statement = 'Luna was unable to get artifacts config. Job: {}. Url: {}'.format(self.job.id, url)
            warning_message = '{}\nError: {}'.format(statement, repr(e))
            logger.warning(warning_message)
            self._raw_artifacts_list = {'error': 'Unable to get config'}

    def _load_configs(self):
        return self.job.config_set.values_list('name', 'content')[::1]

    @property
    def configs_list(self):
        if self._configs is None:
            self._configs = self._load_configs()
        return [name for name, text in self._configs]

    def get_config(self, name):
        if self._configs is None:
            self._configs = self._load_configs()
        if name not in self._configs:
            raise TankAPIError('Config {} unknown'.format(name))
        return self._configs[name]

    @property
    def artifacts_list(self):
        self._artifacts_list_thread.join()
        if self._raw_artifacts_list and self._raw_artifacts_list ['error']:
            raise TankAPIError('Tankapi error: {}'.format(self._raw_artifacts_list['error']))
        return [artifact for artifact in self._raw_artifacts_list['files'] if artifact not in self.configs_list]

    def get_artifact(self, filename):
        if filename not in self.artifacts_list:
            raise TankAPIError('Unknown artifact {}'.format(filename))
        try:
            url = self.address + '/api/v1/tests/{}/logs/{}'.format(self.local_id, filename)
            response = requests.get(url, timeout=settings.ARTIFACTS_GET_REQUEST_TIMEOUT)
        except RequestException as e:
            raise TankAPIError(repr(e))

        return response.text


class TankAPIError(Exception):
    pass
