#
# Copyright 2018-2020 NXP
# SPDX-License-Identifier: Apache-2.0
#
#

"""License text"""

import ctypes
import logging
from .util import status_to_str
from .session import Session
from . import sss_api as apis
from .keyobject import KeyObject
log = logging.getLogger(__name__)


class KeyStore:
    """
    Key Store operation
    """

    # session is instance of Session
    def __init__(self, session_obj):
        """
        Key store context initialization
        :param session_obj: Instance of Session
        """
        if not isinstance(session_obj, Session):
            log.error("%s must be instance of Session", str(session_obj))
            self.keystore = None
            return

        self.keystore = apis.sss_key_store_t()
        self.session = session_obj.session_ctx
        self._keystore_id = ctypes.c_uint32(155)

        if self.session is None:
            self.keystore = None
            return

        status = apis.sss_key_store_context_init(
            ctypes.byref(self.keystore), ctypes.byref(self.session))
        if status != apis.kStatus_SSS_Success:
            log.error("sss_key_store_context_init %s", status_to_str(status))
            self.keystore = None
            return
        log.debug("sss_key_store_context_init %s", status_to_str(status))

        if session_obj.subsystem == apis.kType_SSS_SE_A71CH:
            self._sscp_session = apis.sss_sscp_session_t()
            status = apis.sscp_a71ch_init(
                ctypes.byref(self._sscp_session), ctypes.byref(self.keystore))
            if status != apis.kStatus_SSS_Success:
                log.error("sscp_a71ch_init %s", (status_to_str(status)))
                self.keystore = None
                return
            log.debug("sscp_a71ch_init %s", (status_to_str(status)))

        status = apis.sss_key_store_allocate(ctypes.byref(self.keystore),
                                             self._keystore_id)
        if status != apis.kStatus_SSS_Success:
            log.error("sss_key_store_allocate %s", status_to_str(status))
            self.keystore = None
            return
        log.debug("sss_key_store_allocate %s", status_to_str(status))

    def set_key(self, key_object, data, data_len, key_bit_len, opt, opt_len):  # pylint: disable=too-many-arguments
        """
        Inject key or certificate
        :param key_object: Instance of key object
        :param data: Value to inject
        :param data_len: Length of the value
        :param key_bit_len: Key bit length
        :param opt: Option. Eg: Policy
        :param opt_len: Option length
        :return: Status
        """
        if not isinstance(key_object, KeyObject):
            log.error("%s must be an instance of KeyObject", str(key_object))
            return apis.kStatus_SSS_Fail

        if key_object.keyobject is None:
            log.error("set_key %s", status_to_str(apis.kStatus_SSS_Fail))
            return apis.kStatus_SSS_Fail

        status = apis.sss_key_store_set_key(
            ctypes.byref(self.keystore),
            ctypes.byref(key_object.keyobject),
            ctypes.byref(data),
            data_len, key_bit_len, opt, opt_len)
        if status != apis.kStatus_SSS_Success:
            log.error("sss_key_store_set_key %s", status_to_str(status))
            return status
        log.debug("sss_key_store_set_key %s", status_to_str(status))
        return status

    def save_key_store(self):
        """
        Save key store
        :return: Status
        """
        if self.keystore is None:
            log.error("save_key_store %s", status_to_str(apis.kStatus_SSS_Fail))
            return status_to_str(apis.kStatus_SSS_Fail)
        status = apis.sss_key_store_save(ctypes.byref(self.keystore))
        if status != apis.kStatus_SSS_Success:
            log.error("sss_key_store_save %s", status_to_str(status))
            return status_to_str(status)
        log.debug("sss_key_store_save %s", status_to_str(status))
        return status

    def generate_key(self, key_object, key_len, opt):
        """
        Generate ECC or RSA key
        :param key_object: Instance of key object
        :param key_len: Key length to generate
        :param opt: Options to set. Eg: Policy
        :return: Status
        """
        if not isinstance(key_object, KeyObject):
            log.error("%s must be an instance of KeyObject", str(key_object))
            return apis.kStatus_SSS_Fail

        if key_object.keyobject is None:
            log.error("generate_key %s", status_to_str(apis.kStatus_SSS_Fail))
            return apis.kStatus_SSS_Fail

        status = apis.sss_key_store_generate_key(
            ctypes.byref(self.keystore), ctypes.byref(key_object.keyobject), key_len, opt)

        if status != apis.kStatus_SSS_Success:
            log.error("sss_key_store_generate_key %s", status_to_str(status))
            return status
        log.debug("sss_key_store_generate_key %s", status_to_str(status))
        return status

    def get_key(self, key_object, data, data_len, key_bit_len):
        """
        Retrieve key from secure element
        :param key_object: Instance of key object
        :param data: Output data
        :param data_len: Output data length
        :param key_bit_len: Out put key bit length
        :return: Status
        """
        if not isinstance(key_object, KeyObject):
            log.error("%s must be an instance of KeyObject", str(key_object))
            return apis.kStatus_SSS_Fail

        if key_object.keyobject is None:
            log.error("get_key %s", status_to_str(apis.kStatus_SSS_Fail))
            return apis.kStatus_SSS_Fail

        status = apis.sss_key_store_get_key(
            ctypes.byref(self.keystore), ctypes.byref(key_object.keyobject), ctypes.byref(data),
            ctypes.byref(data_len), ctypes.byref(key_bit_len))

        if status != apis.kStatus_SSS_Success:
            log.error("sss_key_store_get_key %s", status_to_str(status))
            return status
        log.debug("sss_key_store_get_key %s", status_to_str(status))
        return status

    def erase_key(self, key_object):
        """
        Erase key from secure element
        :param key_object: Instance of key object
        :return: Status
        """
        if not isinstance(key_object, KeyObject):
            log.error("%s must be an instance of KeyObject", str(key_object))
            return apis.kStatus_SSS_Fail

        if key_object.keyobject is None:
            log.error("erase_key %s", status_to_str(apis.kStatus_SSS_Fail))
            return apis.kStatus_SSS_Fail

        status = apis.sss_key_store_erase_key(
            ctypes.byref(self.keystore), ctypes.byref(key_object.keyobject))

        if status != apis.kStatus_SSS_Success:
            log.error("sss_key_store_erase_key %s", status_to_str(status))
            return status
        log.debug("sss_key_store_erase_key %s", status_to_str(status))
        return status

    def free(self):
        """
        Release allocated key store
        :return: None
        """
        if self.keystore:
            apis.sss_key_store_context_free(ctypes.byref(self.keystore))
            self.keystore = None
