/*
 *
 *    Copyright (c) 2024 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 "pw_rpc/server.h"
#include "pw_rpc_system_server/rpc_server.h"
#include "pw_rpc_system_server/socket.h"

#include <app/clusters/ecosystem-information-server/ecosystem-information-server.h>
#include <lib/core/CHIPError.h>

#include <string>
#include <thread>

#if defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE
#include "pigweed/rpc_services/FabricBridge.h"
#endif

#include "BridgedDevice.h"
#include "BridgedDeviceManager.h"

using namespace chip;
using namespace chip::app;
using namespace chip::app::Clusters;

namespace {

#if defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE
class FabricBridge final : public chip::rpc::FabricBridge
{
public:
    pw::Status AddSynchronizedDevice(const chip_rpc_SynchronizedDevice & request, pw_protobuf_Empty & response) override;
    pw::Status RemoveSynchronizedDevice(const chip_rpc_SynchronizedDevice & request, pw_protobuf_Empty & response) override;
    pw::Status ActiveChanged(const chip_rpc_KeepActiveChanged & request, pw_protobuf_Empty & response) override;
    pw::Status AdminCommissioningAttributeChanged(const chip_rpc_AdministratorCommissioningChanged & request,
                                                  pw_protobuf_Empty & response) override;
    pw::Status DeviceReachableChanged(const chip_rpc_ReachabilityChanged & request, pw_protobuf_Empty & response) override;
};

pw::Status FabricBridge::AddSynchronizedDevice(const chip_rpc_SynchronizedDevice & request, pw_protobuf_Empty & response)
{
    VerifyOrReturnValue(request.has_id, pw::Status::InvalidArgument());
    ScopedNodeId scopedNodeId(request.id.node_id, request.id.fabric_index);
    ChipLogProgress(NotSpecified, "Received AddSynchronizedDevice: Id=[%d:" ChipLogFormatX64 "]", scopedNodeId.GetFabricIndex(),
                    ChipLogValueX64(scopedNodeId.GetNodeId()));

    auto device = std::make_unique<BridgedDevice>(scopedNodeId);
    device->SetReachable(true);

    BridgedDevice::BridgedAttributes attributes;

    if (request.has_unique_id)
    {
        attributes.uniqueId = request.unique_id;
    }

    if (request.has_vendor_name)
    {
        attributes.vendorName = request.vendor_name;
    }

    if (request.has_vendor_id)
    {
        attributes.vendorId = request.vendor_id;
    }

    if (request.has_product_name)
    {
        attributes.productName = request.product_name;
    }

    if (request.has_product_id)
    {
        attributes.productId = request.product_id;
    }

    if (request.has_node_label)
    {
        attributes.nodeLabel = request.node_label;
    }

    if (request.has_hardware_version)
    {
        attributes.hardwareVersion = request.hardware_version;
    }

    if (request.has_hardware_version_string)
    {
        attributes.hardwareVersionString = request.hardware_version_string;
    }

    if (request.has_software_version)
    {
        attributes.softwareVersion = request.software_version;
    }

    if (request.has_software_version_string)
    {
        attributes.softwareVersionString = request.software_version_string;
    }

    device->SetBridgedAttributes(attributes);
    device->SetIcd(request.has_is_icd && request.is_icd);

    auto result = BridgeDeviceMgr().AddDeviceEndpoint(std::move(device), 1 /* parentEndpointId */);
    if (!result.has_value())
    {
        ChipLogError(NotSpecified, "Failed to add device with Id=[%d:0x" ChipLogFormatX64 "]", scopedNodeId.GetFabricIndex(),
                     ChipLogValueX64(scopedNodeId.GetNodeId()));
        return pw::Status::Unknown();
    }

    BridgedDevice * addedDevice = BridgeDeviceMgr().GetDeviceByScopedNodeId(scopedNodeId);
    VerifyOrDie(addedDevice);

    CHIP_ERROR err = EcosystemInformation::EcosystemInformationServer::Instance().AddEcosystemInformationClusterToEndpoint(
        addedDevice->GetEndpointId());
    VerifyOrDie(err == CHIP_NO_ERROR);

    return pw::OkStatus();
}

pw::Status FabricBridge::RemoveSynchronizedDevice(const chip_rpc_SynchronizedDevice & request, pw_protobuf_Empty & response)
{
    VerifyOrReturnValue(request.has_id, pw::Status::InvalidArgument());
    ScopedNodeId scopedNodeId(request.id.node_id, request.id.fabric_index);
    ChipLogProgress(NotSpecified, "Received RemoveSynchronizedDevice: Id=[%d:" ChipLogFormatX64 "]", scopedNodeId.GetFabricIndex(),
                    ChipLogValueX64(scopedNodeId.GetNodeId()));

    auto removed_idx = BridgeDeviceMgr().RemoveDeviceByScopedNodeId(scopedNodeId);
    if (!removed_idx.has_value())
    {
        ChipLogError(NotSpecified, "Failed to remove device with Id=[%d:0x" ChipLogFormatX64 "]", scopedNodeId.GetFabricIndex(),
                     ChipLogValueX64(scopedNodeId.GetNodeId()));
        return pw::Status::NotFound();
    }

    return pw::OkStatus();
}

pw::Status FabricBridge::ActiveChanged(const chip_rpc_KeepActiveChanged & request, pw_protobuf_Empty & response)
{
    VerifyOrReturnValue(request.has_id, pw::Status::InvalidArgument());
    ScopedNodeId scopedNodeId(request.id.node_id, request.id.fabric_index);
    ChipLogProgress(NotSpecified, "Received ActiveChanged: Id=[%d:" ChipLogFormatX64 "]", scopedNodeId.GetFabricIndex(),
                    ChipLogValueX64(scopedNodeId.GetNodeId()));

    auto * device = BridgeDeviceMgr().GetDeviceByScopedNodeId(scopedNodeId);
    if (device == nullptr)
    {
        ChipLogError(NotSpecified, "Could not find bridged device associated with Id=[%d:0x" ChipLogFormatX64 "]",
                     scopedNodeId.GetFabricIndex(), ChipLogValueX64(scopedNodeId.GetNodeId()));
        return pw::Status::NotFound();
    }

    device->LogActiveChangeEvent(request.promised_active_duration_ms);
    return pw::OkStatus();
}

pw::Status FabricBridge::AdminCommissioningAttributeChanged(const chip_rpc_AdministratorCommissioningChanged & request,
                                                            pw_protobuf_Empty & response)
{
    VerifyOrReturnValue(request.has_id, pw::Status::InvalidArgument());
    ScopedNodeId scopedNodeId(request.id.node_id, request.id.fabric_index);
    ChipLogProgress(NotSpecified, "Received CADMIN attribute change: Id=[%d:" ChipLogFormatX64 "]", scopedNodeId.GetFabricIndex(),
                    ChipLogValueX64(scopedNodeId.GetNodeId()));

    auto * device = BridgeDeviceMgr().GetDeviceByScopedNodeId(scopedNodeId);
    if (device == nullptr)
    {
        ChipLogError(NotSpecified, "Could not find bridged device associated with Id=[%d:0x" ChipLogFormatX64 "]",
                     scopedNodeId.GetFabricIndex(), ChipLogValueX64(scopedNodeId.GetNodeId()));
        return pw::Status::NotFound();
    }

    BridgedDevice::AdminCommissioningAttributes adminCommissioningAttributes;

    uint32_t max_window_status_value =
        static_cast<uint32_t>(chip::app::Clusters::AdministratorCommissioning::CommissioningWindowStatusEnum::kUnknownEnumValue);
    VerifyOrReturnValue(request.window_status < max_window_status_value, pw::Status::InvalidArgument());
    adminCommissioningAttributes.commissioningWindowStatus =
        static_cast<chip::app::Clusters::AdministratorCommissioning::CommissioningWindowStatusEnum>(request.window_status);
    if (request.has_opener_fabric_index)
    {
        VerifyOrReturnValue(request.opener_fabric_index >= chip::kMinValidFabricIndex, pw::Status::InvalidArgument());
        VerifyOrReturnValue(request.opener_fabric_index <= chip::kMaxValidFabricIndex, pw::Status::InvalidArgument());
        adminCommissioningAttributes.openerFabricIndex = static_cast<FabricIndex>(request.opener_fabric_index);
    }

    if (request.has_opener_vendor_id)
    {
        VerifyOrReturnValue(request.opener_vendor_id != chip::VendorId::NotSpecified, pw::Status::InvalidArgument());
        adminCommissioningAttributes.openerVendorId = static_cast<chip::VendorId>(request.opener_vendor_id);
    }

    device->SetAdminCommissioningAttributes(adminCommissioningAttributes);
    return pw::OkStatus();
}

pw::Status FabricBridge::DeviceReachableChanged(const chip_rpc_ReachabilityChanged & request, pw_protobuf_Empty & response)
{
    VerifyOrReturnValue(request.has_id, pw::Status::InvalidArgument());
    ScopedNodeId scopedNodeId(request.id.node_id, request.id.fabric_index);
    ChipLogProgress(NotSpecified, "Received device reachable changed: Id=[%d:" ChipLogFormatX64 "]", scopedNodeId.GetFabricIndex(),
                    ChipLogValueX64(scopedNodeId.GetNodeId()));

    auto * device = BridgeDeviceMgr().GetDeviceByScopedNodeId(scopedNodeId);
    if (device == nullptr)
    {
        ChipLogError(NotSpecified, "Could not find bridged device associated with Id=[%d:0x" ChipLogFormatX64 "]",
                     scopedNodeId.GetFabricIndex(), ChipLogValueX64(scopedNodeId.GetNodeId()));
        return pw::Status::NotFound();
    }

    device->ReachableChanged(request.reachability);

    return pw::OkStatus();
}

FabricBridge fabric_bridge_service;
#endif // defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE

void RegisterServices(pw::rpc::Server & server)
{
#if defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE
    server.RegisterService(fabric_bridge_service);
#endif
}

} // namespace

void RunRpcService()
{
    pw::rpc::system_server::Init();
    RegisterServices(pw::rpc::system_server::Server());
    pw::rpc::system_server::Start();
}

void InitRpcServer(uint16_t rpcServerPort)
{
    pw::rpc::system_server::set_socket_port(rpcServerPort);
    std::thread rpc_service(RunRpcService);
    rpc_service.detach();
}
