#include "Backend.h"
#include "DynamicDevice.h"
#include "main.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)));
    }
    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::Tag(), 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::Tag(), (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::Tag(), (float) atof(str.c_str()));
        break;
    case ZCL_DOUBLE_ATTRIBUTE_TYPE:
        wr.Put(chip::TLV::Tag(), 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::Tag(), (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::Tag(), (uint64_t) strtoll(str.c_str(), nullptr, 10));
        break;

    default:
        // Assume integer
        wr.Put(chip::TLV::Tag(), (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);
}
