/*
 *
 *    Copyright (c) 2021 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.
 */

#include <AppMain.h>
#include <platform/CHIPDeviceLayer.h>
#include <platform/PlatformManager.h>

#include <app-common/zap-generated/attribute-type.h>
#include <app/ConcreteAttributePath.h>
#include <app/EventLogging.h>
#include <app/reporting/reporting.h>
#include <app/util/af-types.h>
#include <app/util/af.h>
#include <app/util/attribute-storage.h>
#include <app/util/util.h>
#include <credentials/DeviceAttestationCredsProvider.h>
#include <credentials/examples/DeviceAttestationCredsExample.h>
#include <lib/core/CHIPError.h>
#include <lib/support/CHIPMem.h>
#include <lib/support/ZclString.h>
#include <platform/CommissionableDataProvider.h>
#include <setup_payload/QRCodeSetupPayloadGenerator.h>
#include <setup_payload/SetupPayload.h>

#include "ActionCluster.h"
#include "Backend.h"
#include "CommissionableInit.h"
#include "Device.h"
#include "main.h"
#include <app/server/Server.h>

#include "AppMain.h"

#include "bridge/BridgeClustersImpl.h"

#ifdef PW_RPC_ENABLED
#include "Rpc.h"
#include "bridge_service.h"
#include "pw_rpc_system_server/rpc_server.h"
static chip::rpc::Bridge bridge_service;
#endif

#include <cassert>
#include <iostream>
#include <vector>

using namespace chip;
using namespace chip::Credentials;
using namespace chip::Inet;
using namespace chip::Transport;
using namespace chip::DeviceLayer;
using namespace chip::app::Clusters;

static EndpointId gCurrentEndpointId;
static EndpointId gFirstDynamicEndpointId;
static Device * gDevices[CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT];
Room gRooms[kMaxRooms];

struct CommonAttributeAccessInterface : public chip::app::AttributeAccessInterface
{
    using chip::app::AttributeAccessInterface::AttributeAccessInterface;

    // Find a cluster given a specific endpoint/cluster. Returns nullptr if no such
    // cluster exists at that path.
    static CommonCluster * FindCluster(const chip::app::ConcreteClusterPath & path);

    CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override;
    CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override;

    CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, TLV::TLVWriter & writer);

    void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override;
    void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override;
};

CommonCluster * CommonAttributeAccessInterface::FindCluster(const chip::app::ConcreteClusterPath & path)
{
    Device * dev = FindDeviceEndpoint(path.mEndpointId);
    if (dev)
    {
        for (auto c : dev->clusters())
        {
            if (c->GetClusterId() == path.mClusterId)
            {
                return static_cast<CommonCluster *>(c);
            }
        }
    }
    return nullptr;
}

CHIP_ERROR CommonAttributeAccessInterface::Read(const chip::app::ConcreteReadAttributePath & aPath,
                                                chip::app::AttributeValueEncoder & aEncoder)
{
    CommonCluster * c = FindCluster(aPath);
    if (!c)
    {
        return CHIP_ERROR_NOT_FOUND;
    }
    AttributeInterface * a = c->FindAttribute(aPath.mAttributeId);
    if (!a)
    {
        return CHIP_ERROR_NOT_FOUND;
    }
    return a->Read(aPath, aEncoder);
}

CHIP_ERROR CommonAttributeAccessInterface::Write(const chip::app::ConcreteDataAttributePath & aPath,
                                                 chip::app::AttributeValueDecoder & aDecoder)
{
    CommonCluster * c = FindCluster(aPath);
    if (!c)
    {
        return CHIP_ERROR_NOT_FOUND;
    }
    return c->ForwardWriteToBridge(aPath, aDecoder);
}

CHIP_ERROR CommonAttributeAccessInterface::Read(const chip::app::ConcreteReadAttributePath & aPath, chip::TLV::TLVWriter & writer)
{
    CommonCluster * c = FindCluster(aPath);
    if (!c)
    {
        return CHIP_ERROR_NOT_FOUND;
    }
    AttributeInterface * a = c->FindAttribute(aPath.mAttributeId);
    if (!a)
    {
        return CHIP_ERROR_NOT_FOUND;
    }
    return a->Read(aPath, writer);
}

void CommonAttributeAccessInterface::OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath)
{
    CommonCluster * c = FindCluster(aPath);
    if (c)
    {
        AttributeInterface * a = c->FindAttribute(aPath.mAttributeId);
        if (a)
        {
            a->ListWriteBegin(aPath);
        }
    }
}

void CommonAttributeAccessInterface::OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful)
{
    CommonCluster * c = FindCluster(aPath);
    if (c)
    {
        AttributeInterface * a = c->FindAttribute(aPath.mAttributeId);
        if (a)
        {
            a->ListWriteEnd(aPath, aWriteWasSuccessful);
        }
    }
}

chip::Optional<chip::ClusterId> LookupClusterByName(const char * name)
{
    for (const auto & cluster : clusters::kKnownClusters)
    {
        if (!strcmp(name, cluster.name))
        {
            return chip::Optional<chip::ClusterId>(cluster.id);
        }
    }
    return chip::Optional<chip::ClusterId>();
}

std::unique_ptr<GeneratedCluster> CreateCluster(chip::ClusterId id)
{
    for (const auto & cluster : clusters::kKnownClusters)
    {
        if (id == cluster.id)
        {
            return std::unique_ptr<GeneratedCluster>(cluster.ctor(::operator new(cluster.size)));
        }
    }
    return nullptr;
}

std::unique_ptr<GeneratedCluster> CreateCluster(const char * name)
{
    auto id = LookupClusterByName(name);
    return id.HasValue() ? CreateCluster(id.Value()) : nullptr;
}

CHIP_ERROR TLVWriteValue(chip::TLV::TLVWriter & wr, const Span<const char> & v)
{
    return wr.PutString(chip::TLV::AnonymousTag(), v);
}

CHIP_ERROR TLVWriteValue(chip::TLV::TLVWriter & wr, const bool & v)
{
    return wr.PutBoolean(chip::TLV::AnonymousTag(), v);
}

template <typename T>
CHIP_ERROR TLVWriteValue(chip::TLV::TLVWriter & wr, const T & v)
{
    return wr.Put(chip::TLV::AnonymousTag(), v);
}

CHIP_ERROR WriteValueToBuffer(const bool & value, chip::Span<uint8_t> buffer)
{
    if (buffer.size() != 1)
    {
        return CHIP_ERROR_INVALID_ARGUMENT;
    }
    *(buffer.data()) = value ? 1 : 0;
    return CHIP_NO_ERROR;
}

template <typename T>
CHIP_ERROR WriteValueToBuffer(const T & value, chip::Span<uint8_t> buffer)
{
    size_t value_size = sizeof(value);
    if (buffer.size() != value_size)
    {
        return CHIP_ERROR_INVALID_ARGUMENT;
    }
    memcpy(buffer.data(), &value, value_size);
    return CHIP_NO_ERROR;
}

template <typename T>
CHIP_ERROR WriteValueToBuffer(chip::TLV::TLVReader & reader, chip::Span<uint8_t> buffer)
{
    T v;
    ReturnErrorOnFailure(chip::app::DataModel::Decode(reader, v));
    return WriteValueToBuffer(v, buffer);
}

// Describes a conversion direction between:
// - A binary buffer (passed from ember internals)
// - A TLV data buffer (used by TLVWriter and TLVReader)
enum ConversionDirection
{
    BUFFER_TO_TLV,
    TLV_TO_BUFFER
};

template <typename T>
CHIP_ERROR PerformTLVBufferConversion(std::vector<uint8_t> * tlvData, chip::Span<uint8_t> buffer,
                                      ConversionDirection convert_direction)
{
    CHIP_ERROR err;
    if (convert_direction == BUFFER_TO_TLV)
    {
        // buffer.size() is ignored here, because it was called from the external write ember callback,
        // which does not provide a buffer size
        chip::TLV::TLVWriter wr;
        wr.Init(tlvData->data(), tlvData->size());
        T value;
        memcpy(&value, buffer.data(), sizeof(T));
        err = TLVWriteValue(wr, value);
        wr.Finalize();
        tlvData->resize(wr.GetLengthWritten());
    }
    else
    {
        chip::TLV::TLVReader rd;
        rd.Init(tlvData->data(), tlvData->size());
        rd.Next();
        err = WriteValueToBuffer<T>(rd, buffer);
    }
    return err;
}

CHIP_ERROR PerformTLVBufferConversionForType(std::vector<uint8_t> * tlvData, chip::Span<uint8_t> buffer, EmberAfAttributeType type,
                                             ConversionDirection convert_direction)
{
    switch (type)
    {
    case ZCL_OCTET_STRING_ATTRIBUTE_TYPE:
    case ZCL_CHAR_STRING_ATTRIBUTE_TYPE:
        return PerformTLVBufferConversion<Span<const char>>(tlvData, buffer, convert_direction);
    case ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE:
    case ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE:
        return PerformTLVBufferConversion<ByteSpan>(tlvData, buffer, convert_direction);
    case ZCL_STRUCT_ATTRIBUTE_TYPE:
        // structs not supported yet
        return CHIP_ERROR_NOT_IMPLEMENTED;
    case ZCL_SINGLE_ATTRIBUTE_TYPE:
        return PerformTLVBufferConversion<float>(tlvData, buffer, convert_direction);
    case ZCL_DOUBLE_ATTRIBUTE_TYPE:
        return PerformTLVBufferConversion<double>(tlvData, buffer, convert_direction);
    case ZCL_INT8S_ATTRIBUTE_TYPE:
    case ZCL_INT16S_ATTRIBUTE_TYPE:
    case ZCL_INT24S_ATTRIBUTE_TYPE:
    case ZCL_INT32S_ATTRIBUTE_TYPE:
    case ZCL_INT40S_ATTRIBUTE_TYPE:
    case ZCL_INT48S_ATTRIBUTE_TYPE:
    case ZCL_INT56S_ATTRIBUTE_TYPE:
    case ZCL_INT64S_ATTRIBUTE_TYPE:
        return PerformTLVBufferConversion<int64_t>(tlvData, buffer, convert_direction);
    case ZCL_INT8U_ATTRIBUTE_TYPE:
    case ZCL_INT16U_ATTRIBUTE_TYPE:
    case ZCL_INT24U_ATTRIBUTE_TYPE:
    case ZCL_INT32U_ATTRIBUTE_TYPE:
    case ZCL_INT40U_ATTRIBUTE_TYPE:
    case ZCL_INT48U_ATTRIBUTE_TYPE:
    case ZCL_INT56U_ATTRIBUTE_TYPE:
    case ZCL_INT64U_ATTRIBUTE_TYPE:
        return PerformTLVBufferConversion<uint64_t>(tlvData, buffer, convert_direction);
    case ZCL_BOOLEAN_ATTRIBUTE_TYPE:
        return PerformTLVBufferConversion<bool>(tlvData, buffer, convert_direction);
    case ZCL_BITMAP32_ATTRIBUTE_TYPE:
        return PerformTLVBufferConversion<uint32_t>(tlvData, buffer, convert_direction);
    default:
        // Assume integer
        return PerformTLVBufferConversion<int64_t>(tlvData, buffer, convert_direction);
    }
}

bool emberAfActionsClusterInstantActionCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
                                                const Actions::Commands::InstantAction::DecodableType & commandData)
{
    // No actions are implemented, just return status NotFound.
    commandObj->AddStatus(commandPath, Protocols::InteractionModel::Status::NotFound);
    return true;
}

EmberAfStatus emberAfExternalAttributeReadCallback(EndpointId endpoint, ClusterId clusterId,
                                                   const EmberAfAttributeMetadata * attributeMetadata, uint8_t * buffer,
                                                   uint16_t maxReadLength)
{
    uint16_t endpointIndex = emberAfGetDynamicIndexFromEndpoint(endpoint);

    if ((endpointIndex >= CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) || (gDevices[endpointIndex] == nullptr))
    {
        ChipLogError(DeviceLayer, "Could not find dynamic endpoint: %d", endpoint);
        return EMBER_ZCL_STATUS_UNSUPPORTED_ENDPOINT;
    }

    chip::app::AttributeAccessInterface * accessInterface = chip::app::GetAttributeAccessOverride(endpoint, clusterId);

    if (accessInterface == nullptr)
    {
        ChipLogError(DeviceLayer, "Cluster %d has no attribute access override", clusterId);
        return EMBER_ZCL_STATUS_FAILURE;
    }

    // adding 64 bytes as padding to include the staging buffer used by
    // TLVReader and TLVWriter, which is 17 bytes
    std::vector<uint8_t> tlvData(attributeMetadata->size + 64);

    // read the attribute and write it to `data`
    chip::TLV::TLVWriter writer;
    writer.Init(tlvData.data(), tlvData.size());

    // this cast is safe because all the registered attribute accessors are of type `CommonAttributeAccessInterface`. See `main()`
    CHIP_ERROR err = static_cast<CommonAttributeAccessInterface *>(accessInterface)
                         ->Read(chip::app::ConcreteDataAttributePath(endpoint, clusterId, attributeMetadata->attributeId), writer);
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "%" CHIP_ERROR_FORMAT, err.Format());
        ChipLogError(DeviceLayer, "Attribute access interface failed to read attribute %d, for endpoint %d cluster %d",
                     attributeMetadata->attributeId, endpoint, clusterId);
        return EMBER_ZCL_STATUS_FAILURE;
    }
    writer.Finalize();
    tlvData.resize(writer.GetLengthWritten());

    // read from `data` and write to `buffer`

    // maxReadLength here is the maximum number of bytes to read from the attribute value and to write into the buffer.
    err = PerformTLVBufferConversionForType(&tlvData, chip::Span<uint8_t>(buffer, maxReadLength), attributeMetadata->attributeType,
                                            TLV_TO_BUFFER);
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "%" CHIP_ERROR_FORMAT, err.Format());
        ChipLogError(DeviceLayer, "Failed to write attribute to buffer. Endpoint %d, Cluster %d, Attribute %d", endpoint, clusterId,
                     attributeMetadata->attributeId);
        return EMBER_ZCL_STATUS_FAILURE;
    }

    return EMBER_ZCL_STATUS_SUCCESS;
}

EmberAfStatus emberAfExternalAttributeWriteCallback(EndpointId endpoint, ClusterId clusterId,
                                                    const EmberAfAttributeMetadata * attributeMetadata, uint8_t * buffer)
{
    uint16_t endpointIndex = emberAfGetDynamicIndexFromEndpoint(endpoint);

    if ((endpointIndex >= CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) || (gDevices[endpointIndex] == nullptr))
    {
        ChipLogError(DeviceLayer, "Could not find dynamic endpoint: %d", endpoint);
        return EMBER_ZCL_STATUS_FAILURE;
    }

    chip::app::AttributeAccessInterface * accessInterface = chip::app::GetAttributeAccessOverride(endpoint, clusterId);

    if (accessInterface == nullptr)
    {
        ChipLogError(DeviceLayer, "Cluster %d has no attribute access override", clusterId);
        return EMBER_ZCL_STATUS_FAILURE;
    }

    // adding 64 bytes as padding to include the staging buffer used by
    // TLVReader and TLVWriter, which is 17 bytes
    std::vector<uint8_t> tlvData(attributeMetadata->size + 64);

    // read from `buffer` and write to `data`

    // buffer size will not be used in this code path, so we set it to 0. See `PerformTLVBufferConversion`
    CHIP_ERROR err = PerformTLVBufferConversionForType(&tlvData, chip::Span<uint8_t>(buffer, 0), attributeMetadata->attributeType,
                                                       BUFFER_TO_TLV);
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "%" CHIP_ERROR_FORMAT, err.Format());
        ChipLogError(DeviceLayer, "Failed to read value from buffer: Endpoint %d, Cluster %d, Attribute %d", endpoint, clusterId,
                     attributeMetadata->attributeId);
        return EMBER_ZCL_STATUS_FAILURE;
    }

    // read from `data` and write to attribute
    chip::TLV::TLVReader reader;
    reader.Init(tlvData.data(), tlvData.size());
    reader.Next();
    chip::app::AttributeValueDecoder decoder(reader, chip::Access::SubjectDescriptor());
    err =
        accessInterface->Write(chip::app::ConcreteReadAttributePath(endpoint, clusterId, attributeMetadata->attributeId), decoder);
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "%" CHIP_ERROR_FORMAT, err.Format());
        ChipLogError(DeviceLayer,
                     "Attribute access interface failed to write attribute value. Endpoint %d, Cluster %d, Attribute %d", endpoint,
                     clusterId, attributeMetadata->attributeId);
        return EMBER_ZCL_STATUS_FAILURE;
    }

    return EMBER_ZCL_STATUS_SUCCESS;
}

Device * FindDeviceEndpoint(chip::EndpointId id)
{
    for (auto dev : gDevices)
    {
        if (dev && dev->GetEndpointId() == id)
        {
            return dev;
        }
    }
    return nullptr;
}

int AddDeviceEndpoint(Device * dev)
{
    uint8_t index = 0;
    while (index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT)
    {
        if (nullptr == gDevices[index])
        {
            gDevices[index] = dev;
            EmberAfStatus ret;
            while (true)
            {
                // Todo: Update this to schedule the work rather than use this lock
                dev->SetEndpointId(gCurrentEndpointId);
                ret =
                    emberAfSetDynamicEndpoint(index, gCurrentEndpointId, dev->endpointType(), dev->versions(), dev->deviceTypes());
                if (ret == EMBER_ZCL_STATUS_SUCCESS)
                {
                    ChipLogProgress(DeviceLayer, "Added device %s to dynamic endpoint %d (index=%d)", dev->GetName(),
                                    gCurrentEndpointId, index);
                    return index;
                }
                if (ret != EMBER_ZCL_STATUS_DUPLICATE_EXISTS)
                {
                    ChipLogProgress(DeviceLayer, "Failed to add dynamic endpoint: %d!", ret);
                    gDevices[index] = nullptr;
                    return -1;
                }
                // Handle wrap condition
                if (++gCurrentEndpointId < gFirstDynamicEndpointId)
                {
                    gCurrentEndpointId = gFirstDynamicEndpointId;
                }
            }
        }
        index++;
    }
    ChipLogProgress(DeviceLayer, "Failed to add dynamic endpoint: No endpoints available!");
    return -1;
}

int RemoveDeviceEndpoint(Device * dev)
{
    uint8_t index = 0;
    while (index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT)
    {
        if (gDevices[index] == dev)
        {
            // Todo: Update this to schedule the work rather than use this lock
            DeviceLayer::StackLock lock;
            EndpointId ep   = emberAfClearDynamicEndpoint(index);
            gDevices[index] = nullptr;
            ChipLogProgress(DeviceLayer, "Removed device %s from dynamic endpoint %d (index=%d)", dev->GetName(), ep, index);
            // Silence complaints about unused ep when progress logging
            // disabled.
            UNUSED_VAR(ep);
            return index;
        }
        index++;
    }
    return -1;
}

Room * FindRoom(const std::string & name)
{
    for (auto & room : gRooms)
    {
        if (room.GetName() == name)
        {
            return &room;
        }
    }
    return nullptr;
}

chip::Span<Action *> GetActionListInfo(chip::EndpointId parentId)
{
    return chip::Span<Action *>();
}

void ApplicationInit()
{
#ifdef PW_RPC_ENABLED
    chip::rpc::Init();

    pw::rpc::system_server::Server().RegisterService(bridge_service);
#endif

    gFirstDynamicEndpointId = static_cast<chip::EndpointId>(
        static_cast<int>(emberAfEndpointFromIndex(static_cast<uint16_t>(emberAfFixedEndpointCount() - 1))) + 1);
    gCurrentEndpointId = gFirstDynamicEndpointId;
    StartUserInput();
}

int main(int argc, char * argv[])
{
    VerifyOrDie(ChipLinuxAppInit(argc, argv) == 0);

    std::vector<CommonAttributeAccessInterface> clusterAccess;
    clusterAccess.reserve(std::extent<decltype(clusters::kKnownClusters)>::value);
    for (auto & entry : clusters::kKnownClusters)
    {
        // Desciptor clusters should not be overridden.
        if (entry.id != chip::app::Clusters::Descriptor::Id)
        {
            clusterAccess.emplace_back(chip::Optional<EndpointId>(), entry.id);
            registerAttributeAccessOverride(&clusterAccess.back());
        }
    }

    ChipLinuxAppMainLoop();
    return 0;
}
