#
#    Copyright (c) 2020 Project CHIP Authors
#    All rights reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License");
#    you may not use this file except in compliance with the License.
#    You may obtain a copy of the License at
#
#        http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS,
#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#    See the License for the specific language governing permissions and
#    limitations under the License.
#

import builtins
import ctypes
import inspect
import logging
import sys
from asyncio.futures import Future
from ctypes import CFUNCTYPE, POINTER, c_bool, c_char_p, c_size_t, c_uint8, c_uint16, c_uint32, c_void_p, cast, py_object
from dataclasses import dataclass
from typing import List, Optional, Type, Union

import chip.exceptions
import chip.interaction_model
from chip.interaction_model import PyInvokeRequestData, TestOnlyPyBatchCommandsOverrides, TestOnlyPyOnDoneInfo
from chip.native import PyChipError

from .ClusterObjects import ClusterCommand

logger = logging.getLogger('chip.cluster.Command')
logger.setLevel(logging.ERROR)


@dataclass
class CommandPath:
    EndpointId: int
    ClusterId: int
    CommandId: int


@dataclass
class InvokeRequestInfo:
    EndpointId: int
    Command: ClusterCommand
    ResponseType: Optional[Type] = None


@dataclass
class Status:
    IMStatus: int
    ClusterStatus: int


@dataclass
class TestOnlyBatchCommandResponse:
    Responses: object
    ResponseMessageCount: int


def FindCommandClusterObject(isClientSideCommand: bool, path: CommandPath):
    ''' Locates the right generated cluster object given a set of parameters.

        isClientSideCommand: True if it is a client-to-server command, else False.
        path: A CommandPath that describes the endpoint, cluster and ID of the command.

        Returns the type of the cluster object if one is found. Otherwise, returns None.
    '''
    for clusterName, obj in inspect.getmembers(sys.modules['chip.clusters.Objects']):
        if ('chip.clusters.Objects' in str(obj)) and inspect.isclass(obj):
            for objName, subclass in inspect.getmembers(obj):
                if inspect.isclass(subclass) and (('Commands') in str(subclass)):
                    for commandName, command in inspect.getmembers(subclass):
                        if inspect.isclass(command):
                            for name, field in inspect.getmembers(command):
                                if ('__dataclass_fields__' in name):
                                    if (field['cluster_id'].default == path.ClusterId) and (field['command_id'].default ==
                                                                                            path.CommandId) and (field['is_client'].default == isClientSideCommand):
                                        return eval('chip.clusters.Objects.' + clusterName + '.Commands.' + commandName)
    return None


class AsyncCommandTransaction:
    def __init__(self, future: Future, eventLoop, expectType: Type):
        self._event_loop = eventLoop
        self._future = future
        self._expect_type = expectType

    def _handleResponse(self, path: CommandPath, status: Status, response: bytes):
        if (len(response) == 0):
            self._future.set_result(None)
        else:
            # If a type hasn't been assigned, let's auto-deduce it.
            if (self._expect_type is None):
                self._expect_type = FindCommandClusterObject(False, path)

            if self._expect_type:
                try:
                    self._future.set_result(
                        self._expect_type.FromTLV(response))
                except Exception as ex:
                    self._handleError(
                        status, 0, ex)
            else:
                self._future.set_result(None)

    def handleResponse(self, path: CommandPath, index: int, status: Status, response: bytes):
        # For AsyncCommandTransaction we only expect to ever get one response so we don't bother
        # checking `index`. We just share a callback API with batch commands. If we ever get a
        # second call to `handleResponse` we will see a different error on trying to set future
        # that has already been set.
        self._event_loop.call_soon_threadsafe(
            self._handleResponse, path, status, response)

    def _handleError(self, imError: Status, chipError: PyChipError, exception: Exception):
        if exception:
            self._future.set_exception(exception)
        elif chipError != 0:
            self._future.set_exception(chipError.to_exception())
        else:
            try:
                # If you got an exception from this call other than AttributeError please
                # add it to the except block below. We changed Exception->AttributeError as
                # that is what we thought we are trying to catch here.
                self._future.set_exception(
                    chip.interaction_model.InteractionModelError(chip.interaction_model.Status(imError.IMStatus), imError.ClusterStatus))
            except AttributeError:
                logger.exception("Failed to map interaction model status received: %s. Remapping to Failure." % imError)
                self._future.set_exception(chip.interaction_model.InteractionModelError(
                    chip.interaction_model.Status.Failure, imError.ClusterStatus))

    def handleError(self, status: Status, chipError: PyChipError):
        self._event_loop.call_soon_threadsafe(
            self._handleError, status, chipError, None
        )

    def handleDone(self):
        ctypes.pythonapi.Py_DecRef(ctypes.py_object(self))


class AsyncBatchCommandsTransaction:
    def __init__(self, future: Future, eventLoop, expectTypes: List[Type]):
        self._event_loop = eventLoop
        self._future = future
        self._expect_types = expectTypes
        default_im_failure = chip.interaction_model.InteractionModelError(
            chip.interaction_model.Status.NoCommandResponse)
        self._responses = [default_im_failure] * len(expectTypes)

    def _handleResponse(self, path: CommandPath, index: int, status: Status, response: bytes):
        if index > len(self._responses):
            self._handleError(status, 0, IndexError(f"CommandSenderCallback has given us an unexpected index value {index}"))
            return

        if status.IMStatus != chip.interaction_model.Status.Success:
            try:
                self._responses[index] = chip.interaction_model.InteractionModelError(
                    chip.interaction_model.Status(status.IMStatus), status.ClusterStatus)
            except AttributeError as ex:
                self._handleError(status, 0, ex)
        elif (len(response) == 0):
            self._responses[index] = None
        else:
            # If a type hasn't been assigned, let's auto-deduce it.
            if (self._expect_types[index] is None):
                self._expect_types[index] = FindCommandClusterObject(False, path)

            if self._expect_types[index]:
                try:
                    # If you got an exception from this call other than AttributeError please
                    # add it to the except block below. We changed Exception->AttributeError as
                    # that is what we thought we are trying to catch here.
                    self._responses[index] = self._expect_types[index].FromTLV(response)
                except AttributeError as ex:
                    self._handleError(status, 0, ex)
            else:
                self._responses[index] = None

    def handleResponse(self, path: CommandPath, index: int, status: Status, response: bytes):
        self._event_loop.call_soon_threadsafe(
            self._handleResponse, path, index, status, response)

    def _handleError(self, imError: Status, chipError: PyChipError, exception: Exception):
        if self._future.done():
            logger.exception(f"Recieved another error. Only expecting one error. imError:{imError}, chipError {chipError}")
            return
        if exception:
            self._future.set_exception(exception)
        elif chipError != 0:
            self._future.set_exception(chipError.to_exception())
        else:
            try:
                # If you got an exception from this call other than AttributeError please
                # add it to the except block below. We changed Exception->AttributeError as
                # that is what we thought we are trying to catch here.
                self._future.set_exception(
                    chip.interaction_model.InteractionModelError(chip.interaction_model.Status(imError.IMStatus), imError.ClusterStatus))
            except AttributeError:
                logger.exception("Failed to map interaction model status received: %s. Remapping to Failure." % imError)
                self._future.set_exception(chip.interaction_model.InteractionModelError(
                    chip.interaction_model.Status.Failure, imError.ClusterStatus))

    def handleError(self, status: Status, chipError: PyChipError):
        self._event_loop.call_soon_threadsafe(
            self._handleError, status, chipError, None
        )

    def _handleDone(self):
        # Future might already be set with exception from `handleError`
        if not self._future.done():
            self._future.set_result(self._responses)
        ctypes.pythonapi.Py_DecRef(ctypes.py_object(self))

    def handleDone(self):
        self._event_loop.call_soon_threadsafe(
            self._handleDone
        )


class TestOnlyAsyncBatchCommandsTransaction(AsyncBatchCommandsTransaction):
    def __init__(self, future: Future, eventLoop, expectTypes: List[Type]):
        self._responseMessageCount = 0
        super().__init__(future, eventLoop, expectTypes)

    def _handleDone(self):
        # Future might already be set with exception from `handleError`
        if not self._future.done():
            self._future.set_result(TestOnlyBatchCommandResponse(self._responses, self._responseMessageCount))
        ctypes.pythonapi.Py_DecRef(ctypes.py_object(self))

    def testOnlyDoneInfo(self, testOnlyDoneInfo: TestOnlyPyOnDoneInfo):
        self._responseMessageCount = testOnlyDoneInfo.responseMessageCount


_OnCommandSenderResponseCallbackFunct = CFUNCTYPE(
    None, py_object, c_uint16, c_uint32, c_uint32, c_size_t, c_uint16, c_uint8, c_void_p, c_uint32)
_OnCommandSenderErrorCallbackFunct = CFUNCTYPE(
    None, py_object, c_uint16, c_uint8, PyChipError)
_OnCommandSenderDoneCallbackFunct = CFUNCTYPE(
    None, py_object)
_TestOnlyOnCommandSenderDoneCallbackFunct = CFUNCTYPE(
    None, py_object, TestOnlyPyOnDoneInfo)


@_OnCommandSenderResponseCallbackFunct
def _OnCommandSenderResponseCallback(closure, endpoint: int, cluster: int, command: int, index: int,
                                     imStatus: int, clusterStatus: int, payload, size):
    data = ctypes.string_at(payload, size)
    closure.handleResponse(CommandPath(endpoint, cluster, command), index, Status(
        imStatus, clusterStatus), data[:])


@_OnCommandSenderErrorCallbackFunct
def _OnCommandSenderErrorCallback(closure, imStatus: int, clusterStatus: int, chiperror: PyChipError):
    closure.handleError(Status(imStatus, clusterStatus), chiperror)


@_OnCommandSenderDoneCallbackFunct
def _OnCommandSenderDoneCallback(closure):
    closure.handleDone()


@_TestOnlyOnCommandSenderDoneCallbackFunct
def _TestOnlyOnCommandSenderDoneCallback(closure, testOnlyDoneInfo: TestOnlyPyOnDoneInfo):
    closure.testOnlyDoneInfo(testOnlyDoneInfo)
    closure.handleDone()


def TestOnlySendCommandTimedRequestFlagWithNoTimedInvoke(future: Future, eventLoop, responseType, device, commandPath, payload):
    ''' ONLY TO BE USED FOR TEST: Sends the payload with a TimedRequest flag but no TimedInvoke transaction
    '''
    if (responseType is not None) and (not issubclass(responseType, ClusterCommand)):
        raise ValueError("responseType must be a ClusterCommand or None")

    handle = chip.native.GetLibraryHandle()
    transaction = AsyncCommandTransaction(future, eventLoop, responseType)

    payloadTLV = payload.ToTLV()
    ctypes.pythonapi.Py_IncRef(ctypes.py_object(transaction))
    return builtins.chipStack.Call(
        lambda: handle.pychip_CommandSender_TestOnlySendCommandTimedRequestNoTimedInvoke(
            ctypes.py_object(transaction), device,
            commandPath.EndpointId, commandPath.ClusterId, commandPath.CommandId, payloadTLV, len(payloadTLV),
            ctypes.c_uint16(0),  # interactionTimeoutMs
            ctypes.c_uint16(0),  # busyWaitMs
            ctypes.c_bool(False)  # suppressResponse
        ))


def SendCommand(future: Future, eventLoop, responseType: Type, device, commandPath: CommandPath, payload: ClusterCommand,
                timedRequestTimeoutMs: Union[None, int] = None, interactionTimeoutMs: Union[None, int] = None, busyWaitMs: Union[None, int] = None,
                suppressResponse: Union[None, bool] = None) -> PyChipError:
    ''' Send a cluster-object encapsulated command to a device and does the following:
            - On receipt of a successful data response, returns the cluster-object equivalent through the provided future.
            - None (on a successful response containing no data)
            - Raises an exception if any errors are encountered.

        If no response type is provided above, the type will be automatically deduced.

        If a valid timedRequestTimeoutMs is provided, a timed interaction will be initiated instead.
        If a valid interactionTimeoutMs is provided, the interaction will terminate with a CHIP_ERROR_TIMEOUT if a response
        has not been received within that timeout. If it isn't provided, a sensible value will be automatically computed that
        accounts for the underlying characteristics of both the transport and the responsiveness of the receiver.
    '''
    if (responseType is not None) and (not issubclass(responseType, ClusterCommand)):
        raise ValueError("responseType must be a ClusterCommand or None")
    if payload.must_use_timed_invoke and timedRequestTimeoutMs is None or timedRequestTimeoutMs == 0:
        raise chip.interaction_model.InteractionModelError(chip.interaction_model.Status.NeedsTimedInteraction)

    handle = chip.native.GetLibraryHandle()
    transaction = AsyncCommandTransaction(future, eventLoop, responseType)

    payloadTLV = payload.ToTLV()
    ctypes.pythonapi.Py_IncRef(ctypes.py_object(transaction))
    return builtins.chipStack.Call(
        lambda: handle.pychip_CommandSender_SendCommand(
            ctypes.py_object(transaction), device,
            c_uint16(0 if timedRequestTimeoutMs is None else timedRequestTimeoutMs), commandPath.EndpointId,
            commandPath.ClusterId, commandPath.CommandId, payloadTLV, len(payloadTLV),
            ctypes.c_uint16(0 if interactionTimeoutMs is None else interactionTimeoutMs),
            ctypes.c_uint16(0 if busyWaitMs is None else busyWaitMs),
            ctypes.c_bool(False if suppressResponse is None else suppressResponse)
        ))


def _BuildPyInvokeRequestData(commands: List[InvokeRequestInfo], timedRequestTimeoutMs: Optional[int], responseTypes, suppressTimedRequestMessage: bool = False) -> List[PyInvokeRequestData]:
    numberOfCommands = len(commands)
    pyBatchCommandsDataArrayType = PyInvokeRequestData * numberOfCommands
    pyBatchCommandsData = pyBatchCommandsDataArrayType()
    for idx, command in enumerate(commands):
        clusterCommand = command.Command
        responseType = command.ResponseType
        if (responseType is not None) and (not issubclass(responseType, ClusterCommand)):
            raise ValueError("responseType must be a ClusterCommand or None")
        if clusterCommand.must_use_timed_invoke and timedRequestTimeoutMs is None or timedRequestTimeoutMs == 0:
            if not suppressTimedRequestMessage:
                raise chip.interaction_model.InteractionModelError(chip.interaction_model.Status.NeedsTimedInteraction)

        payloadTLV = clusterCommand.ToTLV()

        pyBatchCommandsData[idx].commandPath.endpointId = c_uint16(command.EndpointId)
        pyBatchCommandsData[idx].commandPath.clusterId = c_uint32(clusterCommand.cluster_id)
        pyBatchCommandsData[idx].commandPath.commandId = c_uint32(clusterCommand.command_id)
        pyBatchCommandsData[idx].tlvData = cast(c_char_p(bytes(payloadTLV)), c_void_p)
        pyBatchCommandsData[idx].tlvLength = c_size_t(len(payloadTLV))

        responseTypes.append(responseType)

    return pyBatchCommandsData


def SendBatchCommands(future: Future, eventLoop, device, commands: List[InvokeRequestInfo],
                      timedRequestTimeoutMs: Optional[int] = None, interactionTimeoutMs: Optional[int] = None, busyWaitMs: Optional[int] = None,
                      suppressResponse: Optional[bool] = None) -> PyChipError:
    ''' Initiates an InvokeInteraction with the batch commands provided.

    Arguments:
        - timedRequestTimeoutMs: If a valid value is provided, a timed interaction will be initiated.
        - interactionTimeoutMs: If a valid value is provided, the interaction will terminate with a
          CHIP_ERROR_TIMEOUT if a response is not received within the specified timeout. If not provided,
          a suitable value will be automatically computed based on transport characteristics and
          receiver responsiveness.

    Returns:
        - PyChipError: Indicates the outcome of initiating the InvokeRequest. Upon success the caller
          is expected to await on `future` to get result of the InvokeInteraction.

    Results passed via the provided future:
        - Successful InvokeInteraction with path-specific responses (including path-specific errors):
            - A list of responses is returned in the same order as the `commands` argument.
            - Possible response elements:
                - `None`: Successful command execution without additional cluster data.
                - Encapsulated cluster-object: Successful command with response data.
                - interaction_model.Status.*: Command failure with IM Status.
                - interaction_model.Status.NoCommandResponse: No response from the server for
                  a specific command.
        - Non-path-specific error: An `InteractionModelError` exception is raised through the future.
    '''
    handle = chip.native.GetLibraryHandle()

    responseTypes = []
    pyBatchCommandsData = _BuildPyInvokeRequestData(commands, timedRequestTimeoutMs, responseTypes)

    transaction = AsyncBatchCommandsTransaction(future, eventLoop, responseTypes)
    ctypes.pythonapi.Py_IncRef(ctypes.py_object(transaction))

    return builtins.chipStack.Call(
        lambda: handle.pychip_CommandSender_SendBatchCommands(
            py_object(transaction), device,
            c_uint16(0 if timedRequestTimeoutMs is None else timedRequestTimeoutMs),
            c_uint16(0 if interactionTimeoutMs is None else interactionTimeoutMs),
            c_uint16(0 if busyWaitMs is None else busyWaitMs),
            c_bool(False if suppressResponse is None else suppressResponse),
            pyBatchCommandsData, c_size_t(len(pyBatchCommandsData)))
    )


def TestOnlySendBatchCommands(future: Future, eventLoop, device, commands: List[InvokeRequestInfo],
                              timedRequestTimeoutMs: Optional[int] = None, interactionTimeoutMs: Optional[int] = None, busyWaitMs: Optional[int] = None,
                              suppressResponse: Optional[bool] = None, remoteMaxPathsPerInvoke: Optional[int] = None,
                              suppressTimedRequestMessage: bool = False, commandRefsOverride: Optional[List[int]] = None) -> PyChipError:
    ''' ONLY TO BE USED FOR TEST: Send batch commands using various overrides.
    '''
    if suppressTimedRequestMessage and timedRequestTimeoutMs is not None:
        raise ValueError("timedRequestTimeoutMs has non-None value while suppressTimedRequestMessage")

    overrideCommandRefs = None
    if commandRefsOverride is not None:
        if len(commandRefsOverride) != len(commands):
            raise ValueError("Mismatch in the number of elements provided in commandRefsOverride")
        overrideCommandRefsType = c_uint16 * len(commandRefsOverride)
        overrideCommandRefs = overrideCommandRefsType()

    handle = chip.native.GetLibraryHandle()

    responseTypes = []
    pyBatchCommandsData = _BuildPyInvokeRequestData(commands, timedRequestTimeoutMs,
                                                    responseTypes, suppressTimedRequestMessage=suppressTimedRequestMessage)

    transaction = TestOnlyAsyncBatchCommandsTransaction(future, eventLoop, responseTypes)
    ctypes.pythonapi.Py_IncRef(ctypes.py_object(transaction))

    testOnlyOverrides = TestOnlyPyBatchCommandsOverrides()
    testOnlyOverrides.suppressTimedRequestMessage = suppressTimedRequestMessage
    testOnlyOverrides.overrideRemoteMaxPathsPerInvoke = 0 if remoteMaxPathsPerInvoke is None else c_uint16(remoteMaxPathsPerInvoke)
    testOnlyOverrides.overrideCommandRefsList = overrideCommandRefs
    testOnlyOverrides.overrideCommandRefsListLength = 0 if overrideCommandRefs is None else c_size_t(len(overrideCommandRefs))

    return builtins.chipStack.Call(
        lambda: handle.pychip_CommandSender_TestOnlySendBatchCommands(
            py_object(transaction), device,
            c_uint16(0 if timedRequestTimeoutMs is None else timedRequestTimeoutMs),
            c_uint16(0 if interactionTimeoutMs is None else interactionTimeoutMs),
            c_uint16(0 if busyWaitMs is None else busyWaitMs),
            c_bool(False if suppressResponse is None else suppressResponse),
            testOnlyOverrides,
            pyBatchCommandsData, c_size_t(len(pyBatchCommandsData)))
    )


def SendGroupCommand(groupId: int, devCtrl: c_void_p, payload: ClusterCommand, busyWaitMs: Union[None, int] = None) -> PyChipError:
    ''' Send a cluster-object encapsulated group command to a device and does the following:
            - None (on a successful response containing no data)
            - Raises an exception if any errors are encountered.
    '''
    handle = chip.native.GetLibraryHandle()

    payloadTLV = payload.ToTLV()
    return builtins.chipStack.Call(
        lambda: handle.pychip_CommandSender_SendGroupCommand(
            c_uint16(groupId), devCtrl,
            payload.cluster_id, payload.command_id, payloadTLV, len(payloadTLV),
            ctypes.c_uint16(0 if busyWaitMs is None else busyWaitMs),
        ))


def Init():
    handle = chip.native.GetLibraryHandle()

    # Uses one of the type decorators as an indicator for everything being
    # initialized.
    if not handle.pychip_CommandSender_SendCommand.argtypes:
        setter = chip.native.NativeLibraryHandleMethodArguments(handle)

        setter.Set('pychip_CommandSender_SendCommand',
                   PyChipError, [py_object, c_void_p, c_uint16, c_uint32, c_uint32, c_char_p, c_size_t, c_uint16, c_bool])
        setter.Set('pychip_CommandSender_SendBatchCommands',
                   PyChipError, [py_object, c_void_p, c_uint16, c_uint16, c_uint16, c_bool, POINTER(PyInvokeRequestData), c_size_t])
        setter.Set('pychip_CommandSender_TestOnlySendBatchCommands',
                   PyChipError, [py_object, c_void_p, c_uint16, c_uint16, c_uint16, c_bool, TestOnlyPyBatchCommandsOverrides, POINTER(PyInvokeRequestData), c_size_t])
        setter.Set('pychip_CommandSender_TestOnlySendCommandTimedRequestNoTimedInvoke',
                   PyChipError, [py_object, c_void_p, c_uint32, c_uint32, c_char_p, c_size_t, c_uint16, c_bool])
        setter.Set('pychip_CommandSender_SendGroupCommand',
                   PyChipError, [c_uint16, c_void_p, c_uint32, c_uint32, c_char_p, c_size_t, c_uint16])
        setter.Set('pychip_CommandSender_InitCallbacks', None, [
                   _OnCommandSenderResponseCallbackFunct, _OnCommandSenderErrorCallbackFunct, _OnCommandSenderDoneCallbackFunct, _TestOnlyOnCommandSenderDoneCallbackFunct])

    handle.pychip_CommandSender_InitCallbacks(
        _OnCommandSenderResponseCallback, _OnCommandSenderErrorCallback, _OnCommandSenderDoneCallback, _TestOnlyOnCommandSenderDoneCallback)
