/**
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *
 *    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.
 */

#include "ias-zone-client.h"
#include <app/CommandHandler.h>
#include <app/util/af.h>

using namespace chip;

//-----------------------------------------------------------------------------
// Globals

IasZoneDevice emberAfIasZoneClientKnownServers[EMBER_AF_PLUGIN_IAS_ZONE_CLIENT_MAX_DEVICES];

typedef enum
{
    IAS_ZONE_CLIENT_STATE_NONE,
    IAS_ZONE_CLIENT_STATE_DISCOVER_ENDPOINT,
    IAS_ZONE_CLIENT_STATE_SET_CIE_ADDRESS,
    IAS_ZONE_CLIENT_STATE_READ_CIE_ADDRESS,
    IAS_ZONE_CLIENT_STATE_READ_ATTRIBUTES,
} IasZoneClientState;

static IasZoneClientState iasZoneClientState = IAS_ZONE_CLIENT_STATE_NONE;
static uint8_t currentIndex                  = NO_INDEX;
static uint8_t myEndpoint                    = 0;

EmberEventControl emberAfPluginIasZoneClientStateMachineEventControl;

//-----------------------------------------------------------------------------
// Forward Declarations

void readIasZoneServerAttributes(EmberNodeId nodeId);
static void iasClientSaveCommand(void);
static void iasClientLoadCommand(void);

//-----------------------------------------------------------------------------
// Functions

void emberAfIasZoneClusterClientInitCallback(EndpointId endpoint)
{
    emAfClearServers();
    myEndpoint = endpoint;
    iasClientLoadCommand();
}

void emAfClearServers(void)
{
    MEMSET(emberAfIasZoneClientKnownServers, 0xFF, sizeof(IasZoneDevice) * EMBER_AF_PLUGIN_IAS_ZONE_CLIENT_MAX_DEVICES);
}

static void clearState(void)
{
    currentIndex       = 0;
    iasZoneClientState = IAS_ZONE_CLIENT_STATE_NONE;
}

static void setServerZoneStatus(uint8_t serverIndex, uint16_t zoneStatus)
{
    emberAfIasZoneClientKnownServers[serverIndex].zoneStatus = zoneStatus;
    iasClientSaveCommand();
}

static void setServerIeee(uint8_t serverIndex, uint8_t * ieeeAddress)
{
    MEMCOPY(emberAfIasZoneClientKnownServers[serverIndex].ieeeAddress, ieeeAddress, EUI64_SIZE);
    iasClientSaveCommand();
}

static void clearServerIeee(uint8_t serverIndex)
{
    MEMSET(emberAfIasZoneClientKnownServers[serverIndex].ieeeAddress, 0xFF, sizeof(IasZoneDevice));
    iasClientSaveCommand();
}

static void setServerNodeId(uint8_t serverIndex, EmberNodeId nodeId)
{
    emberAfIasZoneClientKnownServers[serverIndex].nodeId = nodeId;
}

static void clearServerNodeId(uint8_t serverIndex)
{
    emberAfIasZoneClientKnownServers[serverIndex].nodeId = EMBER_NULL_NODE_ID;
}

static void setServerZoneState(uint8_t serverIndex, uint8_t zoneState)
{
    emberAfIasZoneClientKnownServers[serverIndex].zoneState = zoneState;
    iasClientSaveCommand();
}

static void setServerEndpoint(uint8_t serverIndex, EndpointId endpoint)
{
    emberAfIasZoneClientKnownServers[serverIndex].endpoint = endpoint;
    iasClientSaveCommand();
}

static void setServerZoneType(uint8_t serverIndex, uint16_t zoneType)
{
    emberAfIasZoneClientKnownServers[serverIndex].zoneType = zoneType;
    iasClientSaveCommand();
}

static void setServerZoneId(uint8_t serverIndex, uint16_t zoneId)
{
    emberAfIasZoneClientKnownServers[serverIndex].zoneId = zoneId;
    iasClientSaveCommand();
}

static void setCurrentIndex(uint8_t serverIndex)
{
    currentIndex = serverIndex;
    iasClientSaveCommand();
}

static void setIasZoneClientState(uint8_t clientState)
{
    iasZoneClientState = clientState;
    iasClientSaveCommand();
}

static void iasClientSaveCommand(void)
{
#if defined(EZSP_HOST) && !defined(EMBER_TEST) && defined(UNIX_HOST)
    FILE * fp;
    uint16_t i, j;

    // save zone server list
    fp = fopen("iaszone.txt", "w");

    for (i = 0; i < EMBER_AF_PLUGIN_IAS_ZONE_CLIENT_MAX_DEVICES; i++)
    {
        if (emberAfIasZoneClientKnownServers[i].zoneId != 0xFF)
        {
            fprintf(fp, "%x %x %x %x %x ", emberAfIasZoneClientKnownServers[i].zoneId,
                    emberAfIasZoneClientKnownServers[i].zoneStatus, emberAfIasZoneClientKnownServers[i].zoneState,
                    emberAfIasZoneClientKnownServers[i].endpoint, emberAfIasZoneClientKnownServers[i].zoneType);
            for (j = 0; j < 8; j++)
            {
                fprintf(fp, "%x ", emberAfIasZoneClientKnownServers[i].ieeeAddress[j]);
            }
        }
    }
    // Write something to mark the end of the file.
    fprintf(fp, "ff");
    int res = fclose(fp);
    assert(res == 0);
#endif //#if defined(EZSP_HOST) && !defined(EMBER_TEST) && defined(UNIX_HOST)
}

static void iasClientLoadCommand(void)
{
#if defined(EZSP_HOST) && !defined(EMBER_TEST) && defined(UNIX_HOST)
    FILE * fp;
    uint16_t i, j;

    unsigned int data1, data2, data3, data4, data5;

    fp = fopen("iaszone.txt", "r");

    if (!fp)
    {
        return;
    }

    for (i = 0; i < EMBER_AF_PLUGIN_IAS_ZONE_CLIENT_MAX_DEVICES; i++)
    {
        if (feof(fp))
        {
            break;
        }
        fscanf(fp, "%x ", &data1);
        if (data1 == 0xff)
        {
            break;
        }
        fscanf(fp, "%x %x %x %x ", &data2, &data3, &data4, &data5);

        emberAfIasZoneClientKnownServers[i].zoneId     = (uint8_t) data1;
        emberAfIasZoneClientKnownServers[i].zoneStatus = (uint16_t) data2;
        emberAfIasZoneClientKnownServers[i].zoneState  = (uint8_t) data3;
        emberAfIasZoneClientKnownServers[i].endpoint   = (uint8_t) data4;
        emberAfIasZoneClientKnownServers[i].zoneType   = (uint16_t) data5;

        for (j = 0; j < 8; j++)
        {
            fscanf(fp, "%x ", &data1);
            emberAfIasZoneClientKnownServers[i].ieeeAddress[j] = (uint8_t) data1;
        }
    }
    int res = fclose(fp);
    assert(res == 0);
#endif // #if defined(EZSP_HOST) && !defined(EMBER_TEST) && defined(UNIX_HOST)
}

static uint8_t findIasZoneServerByIeee(uint8_t * ieeeAddress)
{
    uint8_t i;
    for (i = 0; i < EMBER_AF_PLUGIN_IAS_ZONE_CLIENT_MAX_DEVICES; i++)
    {
        if (0 == memcmp(ieeeAddress, emberAfIasZoneClientKnownServers[i].ieeeAddress, EUI64_SIZE))
        {
            return i;
        }
    }
    return NO_INDEX;
}

static uint8_t findIasZoneServerByNodeId(EmberNodeId nodeId)
{
    uint8_t i;
    for (i = 0; i < EMBER_AF_PLUGIN_IAS_ZONE_CLIENT_MAX_DEVICES; i++)
    {
        if (nodeId == emberAfIasZoneClientKnownServers[i].nodeId)
        {
            return i;
        }
    }

    // If we didn't find the node ID in the table, see if the stack knows about
    // it.
    EmberEUI64 eui64;
    if (emberLookupEui64ByNodeId(nodeId, eui64) == EMBER_SUCCESS)
    {
        i = findIasZoneServerByIeee(eui64);
        if (i != NO_INDEX)
        {
            setServerNodeId(i, nodeId);
        }
    }

    return i;
}

bool emberAfIasZoneClusterZoneStatusChangeNotificationCallback(app::CommandHandler * commandObj, uint16_t zoneStatus,
                                                               uint8_t extendedStatus, uint8_t zoneId, uint16_t delay)
{
    uint8_t serverIndex = findIasZoneServerByNodeId(emberAfCurrentCommand()->source);
    uint8_t status      = EMBER_ZCL_STATUS_NOT_FOUND;
    if (serverIndex != NO_INDEX)
    {
        status = EMBER_ZCL_STATUS_SUCCESS;
        setServerZoneStatus(serverIndex, zoneStatus);

        emberAfIasZoneClusterPrintln("Zone %d status change, 0x%2X from 0x%2X", zoneId, zoneStatus,
                                     emberAfCurrentCommand()->source);

        // The Test case calls for readding attributes after status change.
        //   that is silly for the production device.
        // readIasZoneServerAttributes(emberAfCurrentCommand()->source);
    }
    emberAfSendDefaultResponse(emberAfCurrentCommand(), status);
    return true;
}

bool emberAfIasZoneClusterZoneEnrollRequestCallback(app::CommandHandler * commandObj, uint16_t zoneType, uint16_t manufacturerCode)
{
    EmberAfIasEnrollResponseCode responseCode = EMBER_ZCL_IAS_ENROLL_RESPONSE_CODE_NO_ENROLL_PERMIT;
    uint8_t zoneId                            = UNKNOWN_ZONE_ID;
    uint8_t serverIndex                       = findIasZoneServerByNodeId(emberAfCurrentCommand()->source);
    EmberStatus status;

    if (serverIndex != NO_INDEX)
    {
        responseCode = EMBER_ZCL_IAS_ENROLL_RESPONSE_CODE_SUCCESS;
        zoneId       = serverIndex;
        setServerZoneId(serverIndex, zoneId);
    }
    emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_CLIENT_TO_SERVER), ZCL_IAS_ZONE_CLUSTER_ID,
                              ZCL_ZONE_ENROLL_RESPONSE_COMMAND_ID, "uu", responseCode, zoneId);
    // Need to send this command with our source EUI because the server will
    // check our EUI64 against his CIE Address to see if we're his CIE.
    emberAfGetCommandApsFrame()->options |= EMBER_APS_OPTION_SOURCE_EUI64;
    status = emberAfSendResponse();
    emberAfCorePrintln("Sent enroll response with responseCode: 0x%X, zoneId: 0x%X, status: 0x%X", responseCode, zoneId, status);
    return true;
}

void emberAfPluginIasZoneClientStateMachineEventHandler(void)
{
    emberAfIasZoneClusterPrintln("IAS Zone Client Timeout waiting for message response.");
    emberEventControlSetInactive(emberAfPluginIasZoneClientStateMachineEventControl);
    clearState();
}

static uint8_t addServer(EmberNodeId nodeId, uint8_t * ieeeAddress)
{
    uint8_t i = findIasZoneServerByIeee(ieeeAddress);
    if (i != NO_INDEX)
    {
        return i;
    }

    for (i = 0; i < EMBER_AF_PLUGIN_IAS_ZONE_CLIENT_MAX_DEVICES; i++)
    {
        const uint8_t unsetEui64[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
        if (0 == memcmp(emberAfIasZoneClientKnownServers[i].ieeeAddress, unsetEui64, EUI64_SIZE))
        {
            setServerIeee(i, ieeeAddress);
            setServerNodeId(i, nodeId);
            setServerEndpoint(i, UNKNOWN_ENDPOINT);
            return i;
        }
    }
    return NO_INDEX;
}

static void removeServer(uint8_t * ieeeAddress)
{
    uint8_t index = findIasZoneServerByIeee(ieeeAddress);
    clearServerIeee(index);
    clearServerNodeId(index);
}

static EmberStatus sendCommand(EmberNodeId destAddress)
{
    emberAfSetCommandEndpoints(myEndpoint, emberAfIasZoneClientKnownServers[currentIndex].endpoint);
    EmberStatus status = emberAfSendCommandUnicast(MessageSendDestination::Direct(destAddress));
    emberAfIasZoneClusterPrintln("Sent IAS Zone Client Command to 0x%2X (%d -> %d) status: 0x%X", destAddress, myEndpoint,
                                 emberAfIasZoneClientKnownServers[currentIndex].endpoint, status);
    if (status != EMBER_SUCCESS)
    {
        clearState();
    }
    return status;
}

static void setCieAddress(EmberNodeId destAddress)
{
    uint8_t writeAttributes[] = {
        EMBER_LOW_BYTE(ZCL_IAS_CIE_ADDRESS_ATTRIBUTE_ID),
        EMBER_HIGH_BYTE(ZCL_IAS_CIE_ADDRESS_ATTRIBUTE_ID),
        ZCL_IEEE_ADDRESS_ATTRIBUTE_TYPE,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0, // ieee (filled in later)
    };
    emberAfGetEui64(&writeAttributes[3]);
    emberAfFillExternalBuffer((ZCL_GLOBAL_COMMAND | ZCL_FRAME_CONTROL_CLIENT_TO_SERVER), ZCL_IAS_ZONE_CLUSTER_ID,
                              ZCL_WRITE_ATTRIBUTES_COMMAND_ID, "b", writeAttributes, sizeof(writeAttributes));
    emberAfIasZoneClusterPrintln("Writing CIE Address to IAS Zone Server");
    if (EMBER_SUCCESS == sendCommand(destAddress))
    {
        setIasZoneClientState(IAS_ZONE_CLIENT_STATE_SET_CIE_ADDRESS);
    }
}

static void iasZoneClientServiceDiscoveryCallback(const EmberAfServiceDiscoveryResult * result)
{
    if (result->status == EMBER_AF_UNICAST_SERVICE_DISCOVERY_COMPLETE_WITH_RESPONSE &&
        result->zdoRequestClusterId == MATCH_DESCRIPTORS_REQUEST)
    {
        const EmberAfEndpointList * endpointList = (const EmberAfEndpointList *) result->responseData;
        if (endpointList->count > 0)
        {
            setServerEndpoint(currentIndex, endpointList->list[0]);
            emberAfIasZoneClusterPrintln("Device 0x%2X supports IAS Zone Server", result->matchAddress);
            setCieAddress(result->matchAddress);
            return;
        }
    }
    clearState();
}

static void checkForIasZoneServer(EmberNodeId emberNodeId, uint8_t * ieeeAddress)
{
    uint8_t endpointIndex = emberAfIndexFromEndpoint(myEndpoint);
    uint8_t serverIndex   = addServer(emberNodeId, ieeeAddress);

    if (serverIndex == NO_INDEX)
    {
        emberAfIasZoneClusterPrintln("Error: Could not add IAS Zone server.");
        return;
    }

    setCurrentIndex(serverIndex);

    if (emberAfIasZoneClientKnownServers[serverIndex].endpoint != UNKNOWN_ENDPOINT)
    {
        // If a remote endpoint that you have already seen announces itself,
        // write your IEEE in them just in case they left and are rejoining. --agkeesle
        // Bug: EMAPPFWKV2-1078
        setCieAddress(emberNodeId);
        emberAfIasZoneClusterPrintln("Node 0x%2X already known to IAS client", emberNodeId);
        return;
    }

    EmberStatus status = emberAfFindDevicesByCluster(emberNodeId, ZCL_IAS_ZONE_CLUSTER_ID,
                                                     true, // server cluster?
                                                     iasZoneClientServiceDiscoveryCallback);

    if (status != EMBER_SUCCESS)
    {
        emberAfIasZoneClusterPrintln("Error: Failed to initiate service discovery for IAS Zone Server 0x%2X", emberNodeId);
        clearState();
    }
}

void emberAfPluginIasZoneClientZdoMessageReceivedCallback(EmberNodeId emberNodeId, EmberApsFrame * apsFrame, uint8_t * message,
                                                          uint16_t length)
{
    emberAfIasZoneClusterPrintln("Incoming ZDO, Cluster: 0x%2X", apsFrame->clusterId);
    if (apsFrame->clusterId == END_DEVICE_ANNOUNCE)
    {
        checkForIasZoneServer(emberNodeId, &(message[3]));
    }
}

void readIasZoneServerAttributes(EmberNodeId nodeId)
{
    uint8_t iasZoneAttributeIds[] = {
        EMBER_LOW_BYTE(ZCL_ZONE_STATE_ATTRIBUTE_ID),  EMBER_HIGH_BYTE(ZCL_ZONE_STATE_ATTRIBUTE_ID),

        EMBER_LOW_BYTE(ZCL_ZONE_TYPE_ATTRIBUTE_ID),   EMBER_HIGH_BYTE(ZCL_ZONE_TYPE_ATTRIBUTE_ID),

        EMBER_LOW_BYTE(ZCL_ZONE_STATUS_ATTRIBUTE_ID), EMBER_HIGH_BYTE(ZCL_ZONE_STATUS_ATTRIBUTE_ID),
    };
    emberAfFillExternalBuffer((ZCL_GLOBAL_COMMAND | ZCL_FRAME_CONTROL_CLIENT_TO_SERVER), ZCL_IAS_ZONE_CLUSTER_ID,
                              ZCL_READ_ATTRIBUTES_COMMAND_ID, "b", iasZoneAttributeIds, sizeof(iasZoneAttributeIds));
    if (EMBER_SUCCESS == sendCommand(nodeId))
    {
        setIasZoneClientState(IAS_ZONE_CLIENT_STATE_READ_ATTRIBUTES);
    }
}

void readIasZoneServerCieAddress(EmberNodeId nodeId)
{
    uint8_t iasZoneAttributeIds[] = {
        EMBER_LOW_BYTE(ZCL_IAS_CIE_ADDRESS_ATTRIBUTE_ID),
        EMBER_HIGH_BYTE(ZCL_IAS_CIE_ADDRESS_ATTRIBUTE_ID),
    };
    emberAfFillExternalBuffer((ZCL_GLOBAL_COMMAND | ZCL_FRAME_CONTROL_CLIENT_TO_SERVER), ZCL_IAS_ZONE_CLUSTER_ID,
                              ZCL_READ_ATTRIBUTES_COMMAND_ID, "b", iasZoneAttributeIds, sizeof(iasZoneAttributeIds));
    if (EMBER_SUCCESS == sendCommand(nodeId))
    {
        setIasZoneClientState(IAS_ZONE_CLIENT_STATE_READ_CIE_ADDRESS);
    }
}

void emberAfPluginIasZoneClientWriteAttributesResponseCallback(ClusterId clusterId, uint8_t * buffer, uint16_t bufLen)
{
    if (clusterId == ZCL_IAS_ZONE_CLUSTER_ID && iasZoneClientState == IAS_ZONE_CLIENT_STATE_SET_CIE_ADDRESS &&
        buffer[0] == EMBER_ZCL_STATUS_SUCCESS)
    {
        readIasZoneServerCieAddress(emberAfCurrentCommand()->source);
        return;
    }
    return;
}

void emberAfPluginIasZoneClientReadAttributesResponseCallback(ClusterId clusterId, uint8_t * buffer, uint16_t bufLen)
{
    uint8_t zoneStatus, zoneType, zoneState;
    if (clusterId == ZCL_IAS_ZONE_CLUSTER_ID &&
        (iasZoneClientState == IAS_ZONE_CLIENT_STATE_READ_ATTRIBUTES ||
         iasZoneClientState == IAS_ZONE_CLIENT_STATE_READ_CIE_ADDRESS))
    {
        uint16_t i = 0;
        while ((i + 3) <= bufLen)
        { // 3 to insure we can read at least the attribute ID
          // and the status
            AttributeId attributeId = buffer[i] + (buffer[i + 1] << 8);
            uint8_t status          = buffer[i + 2];
            i += 3;
            // emberAfIasZoneClusterPrintln("Parsing Attribute 0x%2X, Status: 0x%X", attributeId, status);
            if (status == EMBER_ZCL_STATUS_SUCCESS)
            {
                if ((i + 1) > bufLen)
                {
                    // Too short, dump the message.
                    return;
                }
                i++; // skip the type of the attribute.  We already know what it should be.
                switch (attributeId)
                {
                case ZCL_ZONE_STATUS_ATTRIBUTE_ID:
                    if ((i + 2) > bufLen)
                    {
                        // Too short, dump the message.
                        return;
                    }
                    zoneStatus = (buffer[i] + (buffer[i + 1] << 8));
                    setServerZoneStatus(currentIndex, zoneStatus);
                    i += 2;
                    break;
                case ZCL_ZONE_TYPE_ATTRIBUTE_ID:
                    if ((i + 2) > bufLen)
                    {
                        // Too short, dump the message.
                        return;
                    }
                    zoneType = (buffer[i] + (buffer[i + 1] << 8));
                    setServerZoneType(currentIndex, zoneType);
                    i += 2;
                    break;
                case ZCL_ZONE_STATE_ATTRIBUTE_ID:
                    if ((i + 1) > bufLen)
                    {
                        // Too short, dump the message
                        return;
                    }
                    zoneState = buffer[i];
                    setServerZoneState(currentIndex, zoneState);
                    i++;
                    break;
                case ZCL_IAS_CIE_ADDRESS_ATTRIBUTE_ID: {
                    uint8_t myIeee[EUI64_SIZE];
                    emberAfGetEui64(myIeee);
                    if ((i + 8) > bufLen)
                    {
                        // Too short, dump the message
                    }
                    else if (0 != memcmp(&(buffer[i]), myIeee, EUI64_SIZE))
                    {
                        emberAfIasZoneClusterPrintln("CIE Address not set to mine, removing IAS zone server.");
                        removeServer(&(buffer[i]));
                        clearState();
                    }
                    else
                    {
                        readIasZoneServerAttributes(emberAfCurrentCommand()->source);
                    }
                    return;
                }
                }
            }
        }
        emberAfIasZoneClusterPrintln("Retrieved IAS Zone Server attributes from 0x%2X", emberAfCurrentCommand()->source);
        clearState();
    }
}

void emberAfPluginIasZoneClientZdoCallback(EmberNodeId emberNodeId, EmberApsFrame * apsFrame, uint8_t * message, uint16_t length) {}

void emberAfPluginIasZoneClientWriteAttributesResponseCallback(ClusterId clusterId, uint8_t * buffer, uint16_t bufLen) {}

void emberAfPluginIasZoneClientReadAttributesResponseCallback(ClusterId clusterId, uint8_t * buffer, uint16_t bufLen) {}
