import json
import re
from django.conf import settings
import requests
from webui.exceptions import BadRequestException, UnauthorizedException, ServerErrorException, RedirectException, \
    UnexpectedException, LocationHeaderNotFoundException, NotFoundException


def validate_response(response):
    if 200 <= response.status_code < 300:
        return True
    return False


def status_code_to_exception(status_code):
    if status_code == 400:
        return BadRequestException()
    if status_code == 401:
        return UnauthorizedException()
    if status_code == 404:
        return NotFoundException()
    if status_code >= 500:
        return ServerErrorException()
    if 300 <= status_code < 400:
        return RedirectException()
    return UnexpectedException()


def get_resource_id_or_raise_exception(resource_name, response):
    if not validate_response(response):
        exception = status_code_to_exception(response.status_code)
        exception.message = response.text
        raise exception
    location = response.headers.get('location')
    pattern = '.+{}\/(?P<id>\w+)'.format(resource_name)
    p = re.compile(pattern)
    m = p.match(location)
    try:
        resource_id = m.group('id')
        return resource_id
    except:
        return UnexpectedException('Could not get the resource ID from the response.')


class Base(object):
    def __init__(self, auth_token=None):
        self.auth_token = auth_token

    def get_url(self, extra=''):
        return '{base_url}{endpoint}{extra}'.format(base_url=settings.API_BASE_URL,
                                                    endpoint=object.__getattribute__(self, '__endpoint__'),
                                                    extra=extra)


class Session(Base):
    __endpoint__ = '/session/'
    __resourcename__ = 'session'

    def create(self, data):
        url = self.get_url()
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.post(url, headers=headers, data=json.dumps(data))
        resource_id = get_resource_id_or_raise_exception(self.__resourcename__, response)
        return resource_id

    def get(self, resource_id):
        url = self.get_url(extra=str(resource_id))
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.get(url, headers=headers)
        if not validate_response(response):
            exception = status_code_to_exception(response.status_code)
            exception.message = response.text
            raise exception
        session = json.loads(response.text)
        return session

    def start(self, resource_id):
        url = self.get_url(extra='{}/{}/'.format(resource_id, 'start'))
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.post(url, headers=headers)
        if not validate_response(response):
            exception = status_code_to_exception(response.status_code)
            exception.message = response.text
            raise exception

    def stop(self, resource_id):
        url = self.get_url(extra='{}/{}/'.format(resource_id, 'stop'))
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.post(url, headers=headers)
        if not validate_response(response):
            exception = status_code_to_exception(response.status_code)
            exception.message = response.text
            raise exception


class TestPlan(Base):
    __endpoint__ = '/testplan/'
    __resourcename__ = 'testplan'

    def create(self, data):
        url = self.get_url()
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.post(url, headers=headers, data=json.dumps(data))
        resource_id = get_resource_id_or_raise_exception(self.__resourcename__, response)
        return resource_id

    def update(self, resource_id, data):
        url = self.get_url(extra=str(resource_id))
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.put(url, headers=headers, data=json.dumps(data))
        if not validate_response(response):
            exception = status_code_to_exception(response.status_code)
            exception.message = response.text
            raise exception

    def get(self, resource_id):
        url = self.get_url(extra=str(resource_id))
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.get(url, headers=headers)
        if not validate_response(response):
            exception = status_code_to_exception(response.status_code)
            exception.message = response.text
            raise exception
        testplan = json.loads(response.text)
        return testplan

    def get_all(self):
        url = self.get_url()
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.get(url, headers=headers)
        if not validate_response(response):
            exception = status_code_to_exception(response.status_code)
            exception.message = response.text
            raise exception
        testplans = json.loads(response.text)
        return testplans

    def delete(self, resource_id):
        url = self.get_url(extra=str(resource_id))
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.delete(url, headers=headers)
        if not validate_response(response):
            exception = status_code_to_exception(response.status_code)
            exception.message = response.text
            raise exception


class Rule(Base):
    __endpoint__ = '/testplan/{testplan_id}/rule/'
    __resourcename__ = 'rule'

    def __init__(self, testplan_id, auth_token=None):
        self.auth_token = auth_token
        self.__endpoint__ = self.__endpoint__.format(testplan_id=testplan_id)

    def create(self, data):
        url = self.get_url()
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.post(url, headers=headers, data=json.dumps(data))
        resource_id = get_resource_id_or_raise_exception(self.__resourcename__, response)
        return resource_id

    def update(self, resource_id, data):
        url = self.get_url(extra=str(resource_id))
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.put(url, headers=headers, data=json.dumps(data))
        if not validate_response(response):
            exception = status_code_to_exception(response.status_code)
            exception.message = response.text
            raise exception

    def get(self, resource_id):
        url = self.get_url(extra=str(resource_id))
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.get(url, headers=headers)
        if not validate_response(response):
            exception = status_code_to_exception(response.status_code)
            exception.message = response.text
            raise exception
        rule = json.loads(response.text)
        return rule

    def get_all(self):
        url = self.get_url()
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.get(url, headers=headers)
        if not validate_response(response):
            exception = status_code_to_exception(response.status_code)
            exception.message = response.text
            raise exception
        resource = json.loads(response.text)
        return resource


class Recording(Base):
    __endpoint__ = '/recording/'
    __resourcename__ = 'recording'

    def create(self, data):
        url = self.get_url()
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.post(url, headers=headers, data=json.dumps(data))
        resource_id = get_resource_id_or_raise_exception(self.__resourcename__, response)
        return resource_id

    def get(self, resource_id):
        url = self.get_url(extra=str(resource_id))
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.get(url, headers=headers)
        if not validate_response(response):
            exception = status_code_to_exception(response.status_code)
            exception.message = response.text
            raise exception
        recording = json.loads(response.text)
        return recording

    def get_all(self):
        url = self.get_url()
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.get(url, headers=headers)
        if not validate_response(response):
            exception = status_code_to_exception(response.status_code)
            exception.message = response.text
            raise exception
        recordings = json.loads(response.text)
        return recordings

    def update(self, resource_id, data):
        url = self.get_url(extra=str(resource_id))
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.put(url, headers=headers, data=json.dumps(data))
        if not validate_response(response):
            exception = status_code_to_exception(response.status_code)
            exception.message = response.text
            raise exception

    def start(self, resource_id):
        url = self.get_url(extra='{}/{}'.format(resource_id, 'start'))
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.post(url, headers=headers)
        if not validate_response(response):
            exception = status_code_to_exception(response.status_code)
            exception.message = response.text
            raise exception

    def stop(self, resource_id):
        url = self.get_url(extra='{}/{}'.format(resource_id, 'stop'))
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.post(url, headers=headers)
        if not validate_response(response):
            exception = status_code_to_exception(response.status_code)
            exception.message = response.text
            raise exception


class QoS(Base):
    __endpoint__ = '/qos/'
    __resourcename__ = 'qos'

    def create(self, data):
        url = self.get_url()
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.post(url, headers=headers, data=json.dumps(data))
        resource_id = get_resource_id_or_raise_exception(self.__resourcename__, response)
        return resource_id

    def update(self, resource_id, data):
        url = self.get_url(extra=str(resource_id))
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.put(url, headers=headers, data=json.dumps(data))
        if not validate_response(response):
            exception = status_code_to_exception(response.status_code)
            exception.message = response.text
            raise exception

    def get(self, resource_id):
        url = self.get_url(extra=str(resource_id))
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.get(url, headers=headers)
        if not validate_response(response):
            exception = status_code_to_exception(response.status_code)
            exception.message = response.text
            raise exception
        qos = json.loads(response.text)
        return qos

    def get_all(self):
        url = self.get_url()
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.get(url, headers=headers)
        if not validate_response(response):
            exception = status_code_to_exception(response.status_code)
            exception.message = response.text
            raise exception
        qos = json.loads(response.text)
        return qos

    def delete(self, resource_id):
        url = self.get_url(extra=str(resource_id))
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.delete(url, headers=headers)
        if not validate_response(response):
            exception = status_code_to_exception(response.status_code)
            exception.message = response.text
            raise exception


class ServerOverload(Base):
    __endpoint__ = '/serveroverload/'
    __resourcename__ = 'serveroverload'

    def create(self, data):
        url = self.get_url()
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.post(url, headers=headers, data=json.dumps(data))
        resource_id = get_resource_id_or_raise_exception(self.__resourcename__, response)
        return resource_id

    def update(self, resource_id, data):
        url = self.get_url(extra=str(resource_id))
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.put(url, headers=headers, data=json.dumps(data))
        if not validate_response(response):
            exception = status_code_to_exception(response.status_code)
            exception.message = response.text
            raise exception

    def get(self, resource_id):
        url = self.get_url(extra=str(resource_id))
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.get(url, headers=headers)
        if not validate_response(response):
            exception = status_code_to_exception(response.status_code)
            exception.message = response.text
            raise exception
        profile = json.loads(response.text)
        return profile

    def get_all(self):
        url = self.get_url()
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.get(url, headers=headers)
        if not validate_response(response):
            exception = status_code_to_exception(response.status_code)
            exception.message = response.text
            raise exception
        profile = json.loads(response.text)
        return profile

    def delete(self, resource_id):
        url = self.get_url(extra=str(resource_id))
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.delete(url, headers=headers)
        if not validate_response(response):
            exception = status_code_to_exception(response.status_code)
            exception.message = response.text
            raise exception


class Logs(Base):
    __endpoint__ = '/log/'
    __resourcename__ = 'log'

    def stats(self):
        url = self.get_url(extra='stats')
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.get(url, headers=headers)
        if not validate_response(response):
            exception = status_code_to_exception(response.status_code)
            exception.message = response.text
            raise exception
        stats = json.loads(response.text)
        return stats

    def get(self, start, length, component, levels, date_from, date_to, msg):
        url = self.get_url(
            extra='?start={}&limit={}&component={}&levels={}&from={}&to={}&msg={}'.format(start, length, component,
                                                                                          levels,
                                                                                          date_from, date_to, msg))
        headers = {'X-Auth-Token': self.auth_token}
        response = requests.get(url, headers=headers)
        if not validate_response(response):
            exception = status_code_to_exception(response.status_code)
            exception.message = response.text
            raise exception
        logs = json.loads(response.text)
        return logs
[((26, 11, 26, 32), 'webui.exceptions.UnexpectedException', 'UnexpectedException', ({}, {}), '()', False, 'from webui.exceptions import BadRequestException, UnauthorizedException, ServerErrorException, RedirectException, UnexpectedException, LocationHeaderNotFoundException, NotFoundException\n'), ((36, 8, 36, 27), 're.compile', 're.compile', ({(36, 19, 36, 26): 'pattern'}, {}), '(pattern)', False, 'import re\n'), ((17, 15, 17, 36), 'webui.exceptions.BadRequestException', 'BadRequestException', ({}, {}), '()', False, 'from webui.exceptions import BadRequestException, UnauthorizedException, ServerErrorException, RedirectException, UnexpectedException, LocationHeaderNotFoundException, NotFoundException\n'), ((19, 15, 19, 38), 'webui.exceptions.UnauthorizedException', 'UnauthorizedException', ({}, {}), '()', False, 'from webui.exceptions import BadRequestException, UnauthorizedException, ServerErrorException, RedirectException, UnexpectedException, LocationHeaderNotFoundException, NotFoundException\n'), ((21, 15, 21, 34), 'webui.exceptions.NotFoundException', 'NotFoundException', ({}, {}), '()', False, 'from webui.exceptions import BadRequestException, UnauthorizedException, ServerErrorException, RedirectException, UnexpectedException, LocationHeaderNotFoundException, NotFoundException\n'), ((23, 15, 23, 37), 'webui.exceptions.ServerErrorException', 'ServerErrorException', ({}, {}), '()', False, 'from webui.exceptions import BadRequestException, UnauthorizedException, ServerErrorException, RedirectException, UnexpectedException, LocationHeaderNotFoundException, NotFoundException\n'), ((25, 15, 25, 34), 'webui.exceptions.RedirectException', 'RedirectException', ({}, {}), '()', False, 'from webui.exceptions import BadRequestException, UnauthorizedException, ServerErrorException, RedirectException, UnexpectedException, LocationHeaderNotFoundException, NotFoundException\n'), ((69, 19, 69, 53), 'requests.get', 'requests.get', (), '', False, 'import requests\n'), ((74, 18, 74, 43), 'json.loads', 'json.loads', ({(74, 29, 74, 42): 'response.text'}, {}), '(response.text)', False, 'import json\n'), ((80, 19, 80, 54), 'requests.post', 'requests.post', (), '', False, 'import requests\n'), ((89, 19, 89, 54), 'requests.post', 'requests.post', (), '', False, 'import requests\n'), ((119, 19, 119, 53), 'requests.get', 'requests.get', (), '', False, 'import requests\n'), ((124, 19, 124, 44), 'json.loads', 'json.loads', ({(124, 30, 124, 43): 'response.text'}, {}), '(response.text)', False, 'import json\n'), ((130, 19, 130, 53), 'requests.get', 'requests.get', (), '', False, 'import requests\n'), ((135, 20, 135, 45), 'json.loads', 'json.loads', ({(135, 31, 135, 44): 'response.text'}, {}), '(response.text)', False, 'import json\n'), ((141, 19, 141, 56), 'requests.delete', 'requests.delete', (), '', False, 'import requests\n'), ((175, 19, 175, 53), 'requests.get', 'requests.get', (), '', False, 'import requests\n'), ((180, 15, 180, 40), 'json.loads', 'json.loads', ({(180, 26, 180, 39): 'response.text'}, {}), '(response.text)', False, 'import json\n'), ((186, 19, 186, 53), 'requests.get', 'requests.get', (), '', False, 'import requests\n'), ((191, 19, 191, 44), 'json.loads', 'json.loads', ({(191, 30, 191, 43): 'response.text'}, {}), '(response.text)', False, 'import json\n'), ((209, 19, 209, 53), 'requests.get', 'requests.get', (), '', False, 'import requests\n'), ((214, 20, 214, 45), 'json.loads', 'json.loads', ({(214, 31, 214, 44): 'response.text'}, {}), '(response.text)', False, 'import json\n'), ((220, 19, 220, 53), 'requests.get', 'requests.get', (), '', False, 'import requests\n'), ((225, 21, 225, 46), 'json.loads', 'json.loads', ({(225, 32, 225, 45): 'response.text'}, {}), '(response.text)', False, 'import json\n'), ((240, 19, 240, 54), 'requests.post', 'requests.post', (), '', False, 'import requests\n'), ((249, 19, 249, 54), 'requests.post', 'requests.post', (), '', False, 'import requests\n'), ((279, 19, 279, 53), 'requests.get', 'requests.get', (), '', False, 'import requests\n'), ((284, 14, 284, 39), 'json.loads', 'json.loads', ({(284, 25, 284, 38): 'response.text'}, {}), '(response.text)', False, 'import json\n'), ((290, 19, 290, 53), 'requests.get', 'requests.get', (), '', False, 'import requests\n'), ((295, 14, 295, 39), 'json.loads', 'json.loads', ({(295, 25, 295, 38): 'response.text'}, {}), '(response.text)', False, 'import json\n'), ((301, 19, 301, 56), 'requests.delete', 'requests.delete', (), '', False, 'import requests\n'), ((331, 19, 331, 53), 'requests.get', 'requests.get', (), '', False, 'import requests\n'), ((336, 18, 336, 43), 'json.loads', 'json.loads', ({(336, 29, 336, 42): 'response.text'}, {}), '(response.text)', False, 'import json\n'), ((342, 19, 342, 53), 'requests.get', 'requests.get', (), '', False, 'import requests\n'), ((347, 18, 347, 43), 'json.loads', 'json.loads', ({(347, 29, 347, 42): 'response.text'}, {}), '(response.text)', False, 'import json\n'), ((353, 19, 353, 56), 'requests.delete', 'requests.delete', (), '', False, 'import requests\n'), ((367, 19, 367, 53), 'requests.get', 'requests.get', (), '', False, 'import requests\n'), ((372, 16, 372, 41), 'json.loads', 'json.loads', ({(372, 27, 372, 40): 'response.text'}, {}), '(response.text)', False, 'import json\n'), ((381, 19, 381, 53), 'requests.get', 'requests.get', (), '', False, 'import requests\n'), ((386, 15, 386, 40), 'json.loads', 'json.loads', ({(386, 26, 386, 39): 'response.text'}, {}), '(response.text)', False, 'import json\n'), ((42, 15, 42, 86), 'webui.exceptions.UnexpectedException', 'UnexpectedException', ({(42, 35, 42, 85): '"""Could not get the resource ID from the response."""'}, {}), "('Could not get the resource ID from the response.')", False, 'from webui.exceptions import BadRequestException, UnauthorizedException, ServerErrorException, RedirectException, UnexpectedException, LocationHeaderNotFoundException, NotFoundException\n'), ((62, 60, 62, 76), 'json.dumps', 'json.dumps', ({(62, 71, 62, 75): 'data'}, {}), '(data)', False, 'import json\n'), ((103, 60, 103, 76), 'json.dumps', 'json.dumps', ({(103, 71, 103, 75): 'data'}, {}), '(data)', False, 'import json\n'), ((110, 59, 110, 75), 'json.dumps', 'json.dumps', ({(110, 70, 110, 74): 'data'}, {}), '(data)', False, 'import json\n'), ((159, 60, 159, 76), 'json.dumps', 'json.dumps', ({(159, 71, 159, 75): 'data'}, {}), '(data)', False, 'import json\n'), ((166, 59, 166, 75), 'json.dumps', 'json.dumps', ({(166, 70, 166, 74): 'data'}, {}), '(data)', False, 'import json\n'), ((202, 60, 202, 76), 'json.dumps', 'json.dumps', ({(202, 71, 202, 75): 'data'}, {}), '(data)', False, 'import json\n'), ((231, 59, 231, 75), 'json.dumps', 'json.dumps', ({(231, 70, 231, 74): 'data'}, {}), '(data)', False, 'import json\n'), ((263, 60, 263, 76), 'json.dumps', 'json.dumps', ({(263, 71, 263, 75): 'data'}, {}), '(data)', False, 'import json\n'), ((270, 59, 270, 75), 'json.dumps', 'json.dumps', ({(270, 70, 270, 74): 'data'}, {}), '(data)', False, 'import json\n'), ((315, 60, 315, 76), 'json.dumps', 'json.dumps', ({(315, 71, 315, 75): 'data'}, {}), '(data)', False, 'import json\n'), ((322, 59, 322, 75), 'json.dumps', 'json.dumps', ({(322, 70, 322, 74): 'data'}, {}), '(data)', False, 'import json\n')]