# -*- coding: utf-8 -*-
#
# MIT License
# Copyright (c) 2020 Netcloud AG

"""ACI

AciClient for doing Cert based RestCalls to the APIC

NOTES:
openssl req -new -newkey rsa:2048 -days 36500 -nodes -x509 -keyout apicUser.key -out apicUser.crt
"""
import logging
from OpenSSL import crypto
import base64
import requests
import json


class ACICert:
    __logger = logging.getLogger(__name__)

    # ==============================================================================
    # constructor
    # ==============================================================================
    def __init__(self, apicIp, pkPath, certDn):
        self.__logger.debug(f'Constructor called {apicIp} {pkPath} {certDn}')
        self.apicIp = apicIp
        self.baseUrl = 'https://' + self.apicIp + '/api/'
        self.__logger.debug(f'BaseUrl set to: {self.baseUrl}')
        self.pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, open(pkPath, 'rb').read())
        self.certDn = certDn

    # ==============================================================================
    # packCookies
    # ==============================================================================
    def packCookies(self, content) -> {}:
        sigResult = base64.b64encode(crypto.sign(self.pkey, content, 'sha256')).decode()
        # print('sigResultType', type(sigResult), sigResult)
        return {'APIC-Certificate-Fingerprint': 'fingerprint',
                'APIC-Certificate-Algorithm': 'v1.0',
                'APIC-Certificate-DN': self.certDn,
                'APIC-Request-Signature': sigResult}

    # ==============================================================================
    # getJson
    # ==============================================================================
    def getJson(self, uri) -> {}:
        url = self.baseUrl + uri
        self.__logger.debug(f'Get Json called url: {url}')
        content = 'GET/api/' + uri
        cookies = self.packCookies(content)
        r = requests.get(url, cookies=cookies, verify=False)

        # Raise Exception if http Error occurred
        r.raise_for_status()

        self.__logger.debug(f'Successful get Data from APIC: {r.json()}')
        return r.json()['imdata']

    # ==============================================================================
    # postJson
    # ==============================================================================
    def postJson(self, jsonData):
        url = self.baseUrl + 'mo.json'
        self.__logger.debug(f'Post Json called data: {jsonData}')
        data = json.dumps(jsonData, sort_keys=True)
        content = 'POST/api/mo.json' + json.dumps(jsonData)
        cookies = self.packCookies(content)
        r = requests.post(url, data=data, cookies=cookies, verify=False)

        # Raise Exception if http Error occurred
        r.raise_for_status()

        if r.status_code == 200:
            self.__logger.debug(f'Successful Posted Data to APIC: {r.json()}')
            return r.status_code
        else:
            self.__logger.error(f'Error during get occured: {r.json()}')
            return r.status_code, r.json()['imdata'][0]['error']['attributes']['text']

    # ==============================================================================
    # deleteMo
    # ==============================================================================
    def deleteMo(self, dn):
        self.__logger.debug(f'Delete Mo called DN: {dn}')
        url = self.baseUrl + 'mo/' + dn + '.json'
        content = 'DELETE/api/mo/' + dn + '.json'
        cookies = self.packCookies(content)
        r = requests.delete(url, cookies=cookies, verify=False)

        # Raise Exception if http Error occurred
        r.raise_for_status()

        return r.status_code
