import json
import hashlib
import time
import logging
import requests

from .base import Provider as BaseProvider

LOGGER = logging.getLogger(__name__)

ENDPOINTS = {
    'ovh-eu': 'https://eu.api.ovh.com/1.0',
    'ovh-ca': 'https://ca.api.ovh.com/1.0',
    'kimsufi-eu': 'https://eu.api.kimsufi.com/1.0',
    'kimsufi-ca': 'https://ca.api.kimsufi.com/1.0',
    'soyoustart-eu': 'https://eu.api.soyoustart.com/1.0',
    'soyoustart-ca': 'https://ca.api.soyoustart.com/1.0',
}

def ProviderParser(subparser):
    subparser.description = '''
        OVH Provider requires a token with full rights on /domain/*.
        It can be generated for your OVH account on the following URL: 
        https://api.ovh.com/createToken/index.cgi?GET=/domain/*&PUT=/domain/*&POST=/domain/*&DELETE=/domain/*'''
    subparser.add_argument('--auth-entrypoint', help='specify the OVH entrypoint', choices=[
        'ovh-eu', 'ovh-ca', 'soyoustart-eu', 'soyoustart-ca', 'kimsufi-eu', 'kimsufi-ca'
        ])
    subparser.add_argument('--auth-application-key', help='specify the application key')
    subparser.add_argument('--auth-application-secret', help='specify the application secret')
    subparser.add_argument('--auth-consumer-key', help='specify the consumer key')

class Provider(BaseProvider):

    def __init__(self, options, engine_overrides=None):
        super(Provider, self).__init__(options, engine_overrides)

        # Handling missing required parameters
        if not self.options.get('auth_entrypoint'):
            raise Exception('Error, entrypoint is not defined')
        if not self.options.get('auth_application_key'):
            raise Exception('Error, application key is not defined')
        if not self.options.get('auth_application_secret'):
            raise Exception('Error, application secret is not defined')
        if not self.options.get('auth_consumer_key'):
            raise Exception('Error, consumer key is not defined')

        # Construct DNS OVH environment
        self.domain_id = None
        self.endpoint_api = ENDPOINTS.get(self.options.get('auth_entrypoint'))

        # All requests will be done in one HTTPS session
        self.session = requests.Session()

        # Calculate delta time between local and OVH to avoid requests rejection
        server_time = self.session.get('{0}/auth/time'.format(self.endpoint_api)).json()
        self.time_delta = server_time - int(time.time())

    def authenticate(self):
        domain = self.options.get('domain')

        domains = self._get('/domain/zone/')
        if domain not in domains:
            raise Exception('Domain {0} not found'.format(domain))

        status = self._get('/domain/zone/{0}/status'.format(domain))
        if not status['isDeployed']:
            raise Exception('Zone {0} is not deployed'.format(domain))

        self.domain_id = domain

    def create_record(self, type, name, content):
        domain = self.options.get('domain')
        ttl = self.options.get('ttl')

        data = {
            'fieldType': type,
            'subDomain': self._relative_name(name),
            'target': content
        }

        if ttl:
            data['ttl'] = ttl

        result = self._post('/domain/zone/{0}/record'.format(domain), data)
        self._post('/domain/zone/{0}/refresh'.format(domain))

        LOGGER.debug('create_record: %s', result['id'])

        return True

    def list_records(self, type=None, name=None, content=None):
        domain = self.options.get('domain')
        records = []

        params = {}
        if type:
            params['fieldType'] = type
        if name:
            params['subDomain'] = self._relative_name(name)

        record_ids = self._get('/domain/zone/{0}/record'.format(domain), params)

        for record_id in record_ids:
            raw = self._get('/domain/zone/{0}/record/{1}'.format(domain, record_id))
            records.append({
                'type': raw['fieldType'],
                'name': '{0}.{1}'.format(raw['subDomain'], domain),
                'ttl': raw['ttl'],
                'content': raw['target'],
                'id': raw['id']
            })

        if content:
            records = [record for record in records if record['content'].lower() == content.lower()]

        LOGGER.debug('list_records: %s', records)

        return records

    def update_record(self, identifier, type=None, name=None, content=None):
        domain = self.options.get('domain')

        if not identifier:
            records = self.list_records(type, name)
            if len(records) == 1:
                identifier = records[0]['id']
            elif len(records) > 1:
                raise Exception('Several record identifiers match the request')
            else:
                raise Exception('Record identifier could not be found')

        data = {}
        if name:
            data['subDomain'] = self._relative_name(name)
        if content:
            data['target'] = content

        self._put('/domain/zone/{0}/record/{1}'.format(domain, identifier), data)
        self._post('/domain/zone/{0}/refresh'.format(domain))

        LOGGER.debug('update_record: %s', identifier)

        return True

    def delete_record(self, identifier=None, type=None, name=None, content=None):
        domain = self.options.get('domain')

        if not identifier:
            records = self.list_records(type, name, content)
            if len(records) == 1:
                identifier = records[0]['id']
            elif len(records) > 1:
                raise Exception('Several record identifiers match the request')
            else:
                raise Exception('Record identifier could not be found')

        self._delete('/domain/zone/{0}/record/{1}'.format(domain, identifier))
        self._post('/domain/zone/{0}/refresh'.format(domain))

        LOGGER.debug('delete_record: %s', identifier)

        return True

    def _request(self, action='GET', url='/', data=None, query_params=None):
        headers = {}
        target = self.endpoint_api + url
        body = ''

        if data is not None:
            headers['Content-type'] = 'application/json'
            body = json.dumps(data)

        # Get correctly sync time
        now = str(int(time.time()) + self.time_delta)

        headers['X-Ovh-Application'] = self.options.get('auth_application_key')
        headers['X-Ovh-Consumer'] = self.options.get('auth_consumer_key')
        headers['X-Ovh-Timestamp'] = now

        request = requests.Request(action, target, data=body, params=query_params, headers=headers)
        prepared_request = self.session.prepare_request(request)

        # Build OVH API signature for the current request
        signature = hashlib.sha1()
        signature.update('+'.join([
            self.options.get('auth_application_secret'),
            self.options.get('auth_consumer_key'),
            action.upper(),
            prepared_request.url,
            body,
            now
        ]).encode('utf-8'))

        # Sign the request
        prepared_request.headers['X-Ovh-Signature'] = '$1$' + signature.hexdigest()

        result = self.session.send(prepared_request)
        result.raise_for_status()

        return result.json()

@@ -3979,24 +3979,23 @@
 e': 
-'%7B0%7D.%7B1%7D'.format
+self._full_name
 (raw
@@ -4011,16 +4011,8 @@
 in'%5D
-, domain
 ),%0A 

Use _full_name