/*
 *
 *    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.
 */

#pragma once

#include <platform/CHIPDeviceConfig.h>
#include <platform/CommissionableDataProvider.h>

#include "app/clusters/ota-requestor/OTARequestorInterface.h"
#include "app/server/OnboardingCodesUtil.h"
#include "app/server/Server.h"
#include "credentials/FabricTable.h"
#include "device_service/device_service.rpc.pb.h"
#include "platform/CommissionableDataProvider.h"
#include "platform/ConfigurationManager.h"
#include "platform/DiagnosticDataProvider.h"
#include "platform/PlatformManager.h"
#include <platform/DeviceInstanceInfoProvider.h>
#include <setup_payload/QRCodeSetupPayloadGenerator.h>

namespace chip {
namespace rpc {

namespace Internal {
// This class supports changing the commissionable data provider values at
// runtime using the RPCs.
// This class is LazyInit after getting or setting any of it's values. After
// this the class wraps the original CommissionableDataProvider, returning the
// original values for anything which has not been overwritten.
//
// NOTE: Values written do not persist across a reboot.
class CommissionableDataProviderRpcWrapper : public DeviceLayer::CommissionableDataProvider
{
public:
    CHIP_ERROR GetSetupPasscode(uint32_t & setupPasscode) override
    {
        LazyInit();
        if (mPasscodeOverride.has_value())
        {
            setupPasscode = mPasscodeOverride.value();
            return CHIP_NO_ERROR;
        }
        if (mCommissionableDataProvider)
        {
            return mCommissionableDataProvider->GetSetupPasscode(setupPasscode);
        }
        return CHIP_ERROR_INTERNAL;
    }

    // NOTE: Changing the passcode will not change the verifier or anything else
    // this just changes the value returned from GetSetupPasscode.
    // Using this is completely optional, and only really useful for test
    // automation which can read the configured passcode for commissioning
    // after it is changed.
    CHIP_ERROR SetSetupPasscode(uint32_t setupPasscode) override
    {
        LazyInit();
        mPasscodeOverride = setupPasscode;
        return CHIP_NO_ERROR;
    }

    CHIP_ERROR GetSetupDiscriminator(uint16_t & setupDiscriminator) override
    {
        LazyInit();
        if (mDiscriminatorOverride.has_value())
        {
            setupDiscriminator = mDiscriminatorOverride.value();
            return CHIP_NO_ERROR;
        }
        if (mCommissionableDataProvider)
        {
            return mCommissionableDataProvider->GetSetupDiscriminator(setupDiscriminator);
        }
        return CHIP_ERROR_INTERNAL;
    }

    CHIP_ERROR SetSetupDiscriminator(uint16_t setupDiscriminator) override
    {
        LazyInit();
        mDiscriminatorOverride = setupDiscriminator;
        return CHIP_NO_ERROR;
    }

    CHIP_ERROR GetSpake2pIterationCount(uint32_t & iterationCount) override
    {
        LazyInit();
        if (mIterationCountOverride.has_value())
        {
            iterationCount = mIterationCountOverride.value();
            return CHIP_NO_ERROR;
        }
        if (mCommissionableDataProvider)
        {
            return mCommissionableDataProvider->GetSpake2pIterationCount(iterationCount);
        }
        return CHIP_ERROR_INTERNAL;
    }

    CHIP_ERROR SetSpake2pIterationCount(uint32_t iterationCount)
    {
        LazyInit();
        mIterationCountOverride = iterationCount;
        return CHIP_NO_ERROR;
    }

    CHIP_ERROR GetSpake2pSalt(MutableByteSpan & saltBuf) override
    {
        LazyInit();
        if (mSaltOverride.has_value())
        {
            if (mSaltOverride.value().size() > saltBuf.size())
            {
                return CHIP_ERROR_BUFFER_TOO_SMALL;
            }
            std::copy(mSaltOverride.value().begin(), mSaltOverride.value().end(), saltBuf.begin());
            saltBuf.reduce_size(mSaltOverride.value().size());
            return CHIP_NO_ERROR;
        }
        if (mCommissionableDataProvider)
        {
            return mCommissionableDataProvider->GetSpake2pSalt(saltBuf);
        }
        return CHIP_ERROR_INTERNAL;
    }

    CHIP_ERROR SetSpake2pSalt(ByteSpan saltBuf)
    {
        LazyInit();
        if (sizeof(mSaltBuf) < saltBuf.size())
        {
            return CHIP_ERROR_BUFFER_TOO_SMALL;
        }
        std::copy(saltBuf.begin(), saltBuf.end(), mSaltBuf);
        mSaltOverride = ByteSpan(mSaltBuf, saltBuf.size());
        return CHIP_NO_ERROR;
    }

    CHIP_ERROR GetSpake2pVerifier(MutableByteSpan & verifierBuf, size_t & outVerifierLen) override
    {
        LazyInit();
        if (mVerifierOverride.has_value())
        {
            outVerifierLen = mVerifierOverride.value().size();
            if (mVerifierOverride.value().size() > verifierBuf.size())
            {
                return CHIP_ERROR_BUFFER_TOO_SMALL;
            }
            std::copy(mVerifierOverride.value().begin(), mVerifierOverride.value().end(), verifierBuf.begin());
            verifierBuf.reduce_size(mVerifierOverride.value().size());
            return CHIP_NO_ERROR;
        }
        if (mCommissionableDataProvider)
        {
            return mCommissionableDataProvider->GetSpake2pVerifier(verifierBuf, outVerifierLen);
        }

        return CHIP_ERROR_INTERNAL;
    }

    CHIP_ERROR SetSpake2pVerifier(ByteSpan verifierBuf)
    {
        LazyInit();
        if (sizeof(mVerifierBuf) < verifierBuf.size())
        {
            return CHIP_ERROR_BUFFER_TOO_SMALL;
        }
        std::copy(verifierBuf.begin(), verifierBuf.end(), mVerifierBuf);
        mVerifierOverride = ByteSpan(mVerifierBuf, verifierBuf.size());
        return CHIP_NO_ERROR;
    }

private:
    std::optional<uint16_t> mDiscriminatorOverride;
    std::optional<uint32_t> mPasscodeOverride;
    Spake2pVerifierSerialized mVerifierBuf;
    std::optional<ByteSpan> mVerifierOverride;
    uint8_t mSaltBuf[kSpake2p_Max_PBKDF_Salt_Length];
    std::optional<ByteSpan> mSaltOverride;
    std::optional<uint32_t> mIterationCountOverride;
    DeviceLayer::CommissionableDataProvider * mCommissionableDataProvider = nullptr;

    void LazyInit()
    {
        if (!mCommissionableDataProvider)
        {
            mCommissionableDataProvider = DeviceLayer::GetCommissionableDataProvider();
            DeviceLayer::SetCommissionableDataProvider(this);
        }
    }
};
} // namespace Internal

class Device : public pw_rpc::nanopb::Device::Service<Device>
{
public:
    virtual ~Device() = default;

    virtual pw::Status FactoryReset(const pw_protobuf_Empty & request, pw_protobuf_Empty & response)
    {
        DeviceLayer::ConfigurationMgr().InitiateFactoryReset();
        return pw::OkStatus();
    }

    virtual pw::Status Reboot(const pw_protobuf_Empty & request, pw_protobuf_Empty & response)
    {
        return pw::Status::Unimplemented();
    }

    virtual pw::Status TriggerOta(const pw_protobuf_Empty & request, pw_protobuf_Empty & response)
    {
#if CONFIG_CHIP_OTA_REQUESTOR
        chip::DeviceLayer::PlatformMgr().ScheduleWork(
            [](intptr_t) {
                chip::OTARequestorInterface * requestor = chip::GetRequestorInstance();
                if (requestor == nullptr)
                {
                    ChipLogError(SoftwareUpdate, "Can't get the CASESessionManager");
                }
                else
                {
                    requestor->TriggerImmediateQuery();
                }
            },
            reinterpret_cast<intptr_t>(nullptr));
        return pw::OkStatus();
#else
        ChipLogError(AppServer, "Trigger OTA requested, but OTA requestor not compiled in.");
        return pw::Status::Unimplemented();
#endif
    }

    virtual pw::Status SetPairingState(const chip_rpc_PairingState & request, pw_protobuf_Empty & response)
    {
        if (request.pairing_enabled)
        {
            DeviceLayer::ConnectivityMgr().SetBLEAdvertisingEnabled(true);
            DeviceLayer::ConnectivityMgr().SetBLEAdvertisingMode(DeviceLayer::ConnectivityMgr().kFastAdvertising);
        }
        else
        {
            DeviceLayer::ConnectivityMgr().SetBLEAdvertisingEnabled(false);
        }
        return pw::OkStatus();
    }

    virtual pw::Status GetPairingState(const pw_protobuf_Empty & request, chip_rpc_PairingState & response)
    {
        response.pairing_enabled = DeviceLayer::ConnectivityMgr().IsBLEAdvertisingEnabled();
        return pw::OkStatus();
    }

    virtual pw::Status GetDeviceState(const pw_protobuf_Empty & request, chip_rpc_DeviceState & response)
    {
        uint64_t time_since_boot_sec;
        DeviceLayer::GetDiagnosticDataProvider().GetUpTime(time_since_boot_sec);
        response.time_since_boot_millis = time_since_boot_sec * 1000;
        size_t count                    = 0;
        DeviceLayer::StackLock lock;
        for (const FabricInfo & fabricInfo : Server::GetInstance().GetFabricTable())
        {
            if (count < ArraySize(response.fabric_info))
            {
                response.fabric_info[count].fabric_id = fabricInfo.GetFabricId();
                response.fabric_info[count].node_id   = fabricInfo.GetPeerId().GetNodeId();
                count++;
            }
        }
        response.fabric_info_count = count;
        return pw::OkStatus();
    }

    virtual pw::Status GetDeviceInfo(const pw_protobuf_Empty & request, chip_rpc_DeviceInfo & response)
    {

        uint16_t vendor_id;
        if (DeviceLayer::GetDeviceInstanceInfoProvider()->GetVendorId(vendor_id) == CHIP_NO_ERROR)
        {
            response.vendor_id = static_cast<uint32_t>(vendor_id);
        }
        else
        {
            response.vendor_id = CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID;
        }

        uint16_t product_id;
        if (DeviceLayer::GetDeviceInstanceInfoProvider()->GetProductId(product_id) == CHIP_NO_ERROR)
        {
            response.product_id = static_cast<uint32_t>(product_id);
        }
        else
        {
            response.product_id = CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID;
        }

        uint32_t software_version;
        if (DeviceLayer::ConfigurationMgr().GetSoftwareVersion(software_version) == CHIP_NO_ERROR)
        {
            response.software_version = software_version;
        }
        else
        {
            response.software_version = CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION;
        }

        if (DeviceLayer::ConfigurationMgr().GetSoftwareVersionString(response.software_version_string,
                                                                     sizeof(response.software_version_string)) != CHIP_NO_ERROR)
        {
            snprintf(response.software_version_string, sizeof(response.software_version_string),
                     CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING);
        }

        uint32_t code;
        if (DeviceLayer::GetCommissionableDataProvider()->GetSetupPasscode(code) == CHIP_NO_ERROR)
        {
            response.pairing_info.code = code;
            response.has_pairing_info  = true;
        }

        uint16_t discriminator;
        if (DeviceLayer::GetCommissionableDataProvider()->GetSetupDiscriminator(discriminator) == CHIP_NO_ERROR)
        {
            response.pairing_info.discriminator = static_cast<uint32_t>(discriminator);
            response.has_pairing_info           = true;
        }

        if (DeviceLayer::GetDeviceInstanceInfoProvider()->GetSerialNumber(response.serial_number, sizeof(response.serial_number)) !=
            CHIP_NO_ERROR)
        {
            snprintf(response.serial_number, sizeof(response.serial_number), CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER);
        }

        // Create buffer for QR code that can fit max size and null terminator.
        char qrCodeBuffer[chip::QRCodeBasicSetupPayloadGenerator::kMaxQRCodeBase38RepresentationLength + 1];
        chip::MutableCharSpan qrCodeText(qrCodeBuffer);
        if (GetQRCode(qrCodeText, chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE)) == CHIP_NO_ERROR)
        {
            snprintf(response.pairing_info.qr_code, sizeof(response.pairing_info.qr_code), "%s", qrCodeText.data());
            GetQRCodeUrl(response.pairing_info.qr_code_url, sizeof(response.pairing_info.qr_code_url), qrCodeText);
            response.has_pairing_info = true;
        }

        return pw::OkStatus();
    }

    virtual pw::Status GetSpakeInfo(const pw_protobuf_Empty & request, chip_rpc_SpakeInfo & response)
    {
        size_t serializedVerifierLen = 0;
        MutableByteSpan verifierSpan{ response.verifier.bytes };
        if (DeviceLayer::GetCommissionableDataProvider()->GetSpake2pVerifier(verifierSpan, serializedVerifierLen) == CHIP_NO_ERROR)
        {
            response.verifier.size = verifierSpan.size();
            response.has_verifier  = true;
        }

        MutableByteSpan saltSpan{ response.salt.bytes };
        if (DeviceLayer::GetCommissionableDataProvider()->GetSpake2pSalt(saltSpan) == CHIP_NO_ERROR)
        {
            response.salt.size = saltSpan.size();
            response.has_salt  = true;
        }

        if (DeviceLayer::GetCommissionableDataProvider()->GetSpake2pIterationCount(response.iteration_count) == CHIP_NO_ERROR)
        {
            response.has_iteration_count = true;
        }

        return pw::OkStatus();
    }

    virtual pw::Status SetSpakeInfo(const chip_rpc_SpakeInfo & request, pw_protobuf_Empty & response)
    {
        if (request.has_salt)
        {
            mCommissionableDataProvider.SetSpake2pSalt(ByteSpan(request.salt.bytes, request.salt.size));
        }
        if (request.has_iteration_count)
        {
            mCommissionableDataProvider.SetSpake2pIterationCount(request.iteration_count);
        }
        if (request.has_verifier)
        {
            mCommissionableDataProvider.SetSpake2pVerifier(ByteSpan(request.verifier.bytes, request.verifier.size));
        }
        return pw::OkStatus();
    }

    // NOTE: Changing the passcode will not change the verifier or anything else
    // this just changes the value returned from GetSetupPasscode.
    // Using this is completely optional, and only really useful for test
    // automation which can read the configured passcode for commissioning
    // after it is changed.
    virtual pw::Status SetPairingInfo(const chip_rpc_PairingInfo & request, pw_protobuf_Empty & response)
    {
        if (mCommissionableDataProvider.SetSetupPasscode(request.code) != CHIP_NO_ERROR ||
            mCommissionableDataProvider.SetSetupDiscriminator(request.discriminator) != CHIP_NO_ERROR)
        {
            return pw::Status::Unknown();
        }
        return pw::OkStatus();
    }

private:
    Internal::CommissionableDataProviderRpcWrapper mCommissionableDataProvider;
};

} // namespace rpc
} // namespace chip
