#include "Backend.h"
#include "DynamicDevice.h"
#include "main.h"

#include <app-common/zap-generated/attribute-type.h>
#include <platform/PlatformManager.h>

#include <algorithm>
#include <charconv>
#include <future>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <vector>

namespace {

std::unique_ptr<DynamicDevice> g_pending;

// Pseudo-index representing the device being built.
static constexpr int kPendingDeviceIndex = -1;

PropagateWriteCB g_write_cb = [](CommonCluster * cluster, const chip::app::ConcreteDataAttributePath & path,
                                 chip::app::AttributeValueDecoder & decoder) -> CHIP_ERROR {
    CHIP_ERROR ret = cluster->WriteFromBridge(path, decoder);
    printf("Write to ep %d cluster %d attribute %d ret %" CHIP_ERROR_FORMAT "\n", path.mEndpointId, path.mClusterId,
           path.mAttributeId, ret.Format());
    return ret;
};

const char * ParseValue(const std::vector<std::string> & tokens, size_t index, std::string * v)
{
    if (index >= tokens.size())
        return "Missing argument";
    *v = tokens[index];
    return nullptr;
}
const char * ParseValue(const std::vector<std::string> & tokens, size_t index, chip::Optional<std::string> * v)
{
    if (index < tokens.size())
        v->SetValue(tokens[index]);
    return nullptr;
}

template <typename T, typename = std::enable_if<std::is_arithmetic<T>::value>>
const char * ParseValue(const std::vector<std::string> & tokens, size_t index, T * v)
{
    if (index >= tokens.size())
        return "Missing argument";
    const char * start = tokens[index].data();
    const char * end   = start + tokens[index].size();
    auto ret           = std::from_chars(start, end, *v);
    if (ret.ptr != end)
        return "Cannot parse as integer";
    return nullptr;
}

template <typename T, typename = std::enable_if<std::is_arithmetic<T>::value>>
const char * ParseValue(const std::vector<std::string> & tokens, size_t index, chip::Optional<T> * v)
{
    uint32_t temp;
    if (!ParseValue(tokens, index, &temp))
        v->SetValue(temp);
    return nullptr;
}

const char * Parse(const std::vector<std::string> & tokens, size_t index)
{
    if (index >= tokens.size())
        return nullptr;
    return "Unexpected extra tokens";
}

template <typename T, typename... Args>
const char * Parse(const std::vector<std::string> & tokens, size_t index, T arg0, Args... args)
{
    auto ret = ParseValue(tokens, index, arg0);
    return ret ? ret : Parse(tokens, index + 1, args...);
}

void NewDevice(const std::vector<std::string> & tokens)
{
    if (g_pending)
    {
        printf("Already pending device!\n");
        return;
    }

    chip::Optional<std::string> type;
    const char * err = Parse(tokens, 0, &type);
    if (err)
    {
        printf("Error: %s\nExpected [prebuilt-device-type]\n", err);
    }
    else if (!type.HasValue())
    {
        g_pending = std::make_unique<DynamicDevice>();
    }
    else
    {
        printf("Unknown device type %s\nSupported types: switch\n", type.Value().c_str());
    }
}

void AddCluster(const std::vector<std::string> & tokens)
{
    if (!g_pending)
    {
        printf("Expected pending device! Run new-device\n");
        return;
    }
    std::string cluster_name;
    const char * err = Parse(tokens, 0, &cluster_name);
    if (err)
    {
        printf("Error: %s\n", err);
        return;
    }

    auto c = CreateCluster(cluster_name.c_str());
    if (c)
    {
        g_pending->AddCluster(
            std::make_unique<DynamicCluster>(std::move(c), c->GetIncomingCommandList(), c->GetOutgoingCommandList()));
    }
    else
    {
        printf("No such cluster '%s'\n", cluster_name.c_str());
    }
}

void CancelDevice(const std::vector<std::string> & tokens)
{
    const char * err = Parse(tokens, 0);
    if (err)
    {
        printf("Error: %s\n", err);
        return;
    }

    g_pending.reset(nullptr);
}

void FinishDevice(const std::vector<std::string> & tokens)
{
    if (!g_pending)
    {
        printf("Expected pending device! Run new-device\n");
        return;
    }

    const char * err = Parse(tokens, 0);
    if (err)
    {
        printf("Error: %s\n", err);
        return;
    }

    for (auto * c : g_pending->clusters())
        c->SetCallback(&g_write_cb);

    int ep = AddDevice(std::move(g_pending));

    if (ep < 0)
    {
        printf("Failed to add device\n");
    }
    else
    {
        printf("Added device at index %d\n", ep);
    }
}

void RemoveDevice(const std::vector<std::string> & tokens)
{
    uint32_t index;
    const char * err = Parse(tokens, 0, &index);
    if (err)
    {
        printf("Error: %s.\nExpected index of a device\n", err);
        return;
    }
    if (!RemoveDeviceAt(index))
    {
        printf("%d is an invalid index\n", index);
    }
}

void AddType(const std::vector<std::string> & tokens)
{
    if (!g_pending)
    {
        printf("Expected pending device! Run new-device\n");
        return;
    }
    uint32_t type;
    chip::Optional<uint32_t> version;
    const char * err = Parse(tokens, 0, &type, &version);
    if (err)
    {
        printf("Error: %s.\nExpected: type [version]\n", err);
        return;
    }
    EmberAfDeviceType devType = { (uint16_t) type, (uint8_t) version.ValueOr(1u) };
    printf("Adding device type %d ver %d\n", devType.deviceId, devType.deviceVersion);

    g_pending->AddDeviceType(devType);
}

DynamicDevice * FindDevice(int32_t index)
{
    if (index == kPendingDeviceIndex)
    {
        return g_pending.get();
    }
    else if ((uint32_t) index < g_device_impls.size())
    {
        return g_device_impls[(uint32_t) index].get();
    }
    else
    {
        return nullptr;
    }
}

Device * FindEndpoint(int32_t index)
{
    if (index >= 0 && (uint32_t) index < g_device_impls.size())
    {
        return g_devices[(uint32_t) index].get();
    }
    else
    {
        return nullptr;
    }
}

ClusterInterface * FindCluster(DynamicDevice * dev, const std::string & clusterId)
{
    uint32_t id;
    const char * start = clusterId.data();
    const char * end   = start + clusterId.size();
    if (std::from_chars(start, end, id).ptr != end)
    {
        auto r = LookupClusterByName(clusterId.c_str());
        if (r.HasValue())
        {
            return nullptr;
        }
        id = r.Value();
    }

    for (auto * c : dev->clusters())
    {
        if (c->GetClusterId() == id)
        {
            return c;
        }
    }
    return nullptr;
}

const EmberAfAttributeMetadata * FindAttrib(ClusterInterface * cluster, const std::string & attrId)
{
    AttributeInterface * attr = nullptr;
    uint32_t id;
    const char * start = attrId.data();
    const char * end   = start + attrId.size();
    if (std::from_chars(start, end, id).ptr == end)
    {
        attr = cluster->FindAttribute(id);
    }
    if (!attr)
    {
        attr = cluster->FindAttributeByName(chip::CharSpan(attrId.data(), attrId.size()));
    }

    return attr ? &attr->GetMetadata() : nullptr;
}

void ParseValue(std::vector<uint8_t> * data, uint16_t size, const std::string & str, EmberAfAttributeType type)
{
    chip::TLV::TLVWriter wr;
    wr.Init(data->data(), data->size());
    switch (type)
    {
    case ZCL_OCTET_STRING_ATTRIBUTE_TYPE:
    case ZCL_CHAR_STRING_ATTRIBUTE_TYPE:
        wr.PutString(chip::TLV::AnonymousTag(), str.data(), (uint32_t) str.size());
        break;
    case ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE:
    case ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE:
        wr.PutBytes(chip::TLV::AnonymousTag(), (const uint8_t *) str.data(), (uint32_t) str.size());
        break;
    case ZCL_STRUCT_ATTRIBUTE_TYPE:
        // Writing structs not supported yet
        break;
    case ZCL_SINGLE_ATTRIBUTE_TYPE:
        wr.Put(chip::TLV::AnonymousTag(), (float) atof(str.c_str()));
        break;
    case ZCL_DOUBLE_ATTRIBUTE_TYPE:
        wr.Put(chip::TLV::AnonymousTag(), atof(str.c_str()));
        break;
    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:
        wr.Put(chip::TLV::AnonymousTag(), (int64_t) strtoll(str.c_str(), nullptr, 10));
        break;

    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:
        wr.Put(chip::TLV::AnonymousTag(), (uint64_t) strtoll(str.c_str(), nullptr, 10));
        break;

    default:
        // Assume integer
        wr.Put(chip::TLV::AnonymousTag(), (int64_t) strtoll(str.c_str(), nullptr, 10));
        break;
    }
    wr.Finalize();
    data->resize(wr.GetLengthWritten());
}

void SetValue(const std::vector<std::string> & tokens)
{
    std::string attrId;
    int32_t index;
    std::string clusterId;
    std::string value;
    const char * err = Parse(tokens, 0, &index, &clusterId, &attrId, &value);
    if (err)
    {
        printf("Error: %s.\nExpected: deviceIndex clusterId attributeId value\nUse deviceIndex -1 for pending device.\n", err);
        return;
    }

    DynamicDevice * dev = FindDevice(index);
    if (!dev)
    {
        printf("Could not find device at index %d\n", index);
        return;
    }

    ClusterInterface * cluster = FindCluster(dev, clusterId);
    if (!cluster)
    {
        printf("Device does not implement cluster %s\nSupported clusters: ", clusterId.c_str());
        for (auto * c : dev->clusters())
        {
            printf("%d ", c->GetClusterId());
        }
        printf("\n");
        return;
    }

    const EmberAfAttributeMetadata * attr = FindAttrib(cluster, attrId);
    if (!attr)
    {
        printf("Cluster does not implement attr %s\nSupported attributes: ", attrId.c_str());
        for (auto attrMeta : cluster->GetAllAttributes())
        {
            printf("%d ", attrMeta->GetId());
        }
        printf("\n");
        return;
    }

    std::vector<uint8_t> data(attr->size + 64);
    ParseValue(&data, attr->size, value, attr->attributeType);

    chip::TLV::TLVReader rd;
    rd.Init(data.data(), data.size());
    rd.Next();

    if (!cluster->Write(attr->attributeId, rd))
    {
        printf("Write failed\n");
    }
}

void AddRoom(const std::vector<std::string> & tokens)
{
    if (tokens.size() != 1)
    {
        printf("Expected exactly one string\n");
        return;
    }
    auto room = FindRoom(tokens[0]);
    if (room)
    {
        printf("Room already exists\n");
        return;
    }
}

void DelRoom(const std::vector<std::string> & tokens)
{
    if (tokens.size() != 1)
    {
        printf("Expected exactly one string\n");
        return;
    }
    auto room = FindRoom(tokens[0]);
    if (!room)
    {
        printf("No such room\n");
        return;
    }

    room->SetName(std::string());
    while (room->GetEndpointListSize() > 0)
        room->RemoveEndpoint(*room->GetEndpointListData());
}

void AddToRoom(const std::vector<std::string> & tokens)
{
    int32_t index;
    std::string room;
    const char * err = Parse(tokens, 0, &room, &index);
    if (err)
    {
        printf("Error: %s.\nExpected: room index.\n", err);
        return;
    }
    auto roomPtr = FindRoom(tokens[0]);
    if (!roomPtr)
    {
        printf("No such room\n");
        return;
    }
    auto dev = FindEndpoint(index);
    if (!dev)
    {
        printf("No such device\n");
        return;
    }
    roomPtr->AddEndpoint(dev->GetEndpointId());
}

void DelFromRoom(const std::vector<std::string> & tokens)
{
    int32_t index;
    std::string room;
    const char * err = Parse(tokens, 0, &room, &index);
    if (err)
    {
        printf("Error: %s.\nExpected: room index.\n", err);
        return;
    }
    auto roomPtr = FindRoom(tokens[0]);
    if (!roomPtr)
    {
        printf("No such room\n");
        return;
    }
    auto dev = FindEndpoint(index);
    if (!dev)
    {
        printf("No such device\n");
        return;
    }
    roomPtr->RemoveEndpoint(dev->GetEndpointId());
}

void SetParentId(const std::vector<std::string> & tokens)
{
    if (!g_pending)
    {
        printf("Expected pending device! Run new-device\n");
        return;
    }

    int32_t index;
    const char * err = Parse(tokens, 0, &index);
    if (err)
    {
        printf("Error: %s.\nExpected: deviceIndex\n", err);
        return;
    }
    auto dev = FindEndpoint(index);
    if (!dev)
    {
        printf("No such device\n");
        return;
    }
    g_pending->SetParentEndpointId(dev->GetEndpointId());
}

void Help(const std::vector<std::string> & tokens);

struct Command
{
    const char * name;
    const char * desc;
    void (*fn)(const std::vector<std::string> & tokens);
} const commands[] = {
    { "help", "", &Help },
    { "new-device", "[type] - Begin adding a new device. Add device types and clusters, then finish", &NewDevice },
    { "del-device", "index - Remove a device at the specified index", &RemoveDevice },
    { "add-cluster", "name - Add a cluster by name, eg FixedLabel", &AddCluster },
    { "finish-device", "Finish the currently pending device. Clusters and device types are immutable.", &FinishDevice },
    { "cancel-device", "Abort adding a new device", &CancelDevice },
    { "add-type", "id [version] - Add a device type by ID, optionally with a version", &AddType },
    { "set", "deviceIndex clusterId attributeId value - Set a value. deviceIndex -1 for adding device", &SetValue },
    { "set-parent-id", "deviceIndex - Set the parent endpoint ID to the specified device", &SetParentId },
    { "add-room", "name - Add a new named room", &AddRoom },
    { "del-room", "name - Remove an existing named room", &DelRoom },
    { "add-to-room", "name index - Add a device to a named room", &AddToRoom },
    { "del-from-room", "name index - Remove a device from a named room", &DelFromRoom },
};

void Help(const std::vector<std::string> & tokens)
{
    for (auto & cmd : commands)
    {
        printf("%s %s\n", cmd.name, cmd.desc);
    }
}

struct Op
{
    std::vector<std::string> * tokens;
    const Command * command;
    std::promise<void> lock;
};
void ProcessLineOnMatterThread(intptr_t arg)
{
    Op * op = reinterpret_cast<Op *>(arg);
    op->command->fn(*op->tokens);
    op->lock.set_value();
}

void ProcessLine(std::vector<std::string> & tokens)
{
    for (auto & cmd : commands)
    {
        if (tokens[0] == cmd.name)
        {
            tokens.erase(tokens.begin());

            Op op{ &tokens, &cmd };
            chip::DeviceLayer::PlatformMgr().ScheduleWork(&ProcessLineOnMatterThread, reinterpret_cast<intptr_t>(&op));
            // Wait for command completion
            op.lock.get_future().wait();
            return;
        }
    }
    printf("Unknown command '%s'\n", tokens[0].c_str());
}

void * UserInputThread(void *)
{
    std::string line;
    while (true)
    {
        printf("? ");
        std::cin >> std::ws;
        std::getline(std::cin, line);
        if (std::cin.eof())
            break;

        std::istringstream iss(line);
        std::vector<std::string> tokens{ std::istream_iterator<std::string>{ iss }, std::istream_iterator<std::string>{} };

        ProcessLine(tokens);
    }
    return nullptr;
}

} // namespace

void StartUserInput()
{
    pthread_t thread;
    pthread_create(&thread, nullptr, &UserInputThread, nullptr);
}
