/*
 *
 *    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 <ota-provider-common/OTAProviderExample.h>

#include <algorithm>
#include <app-common/zap-generated/cluster-objects.h>
#include <app/clusters/ota-provider/ota-provider-delegate.h>
#include <app/server/Server.h>
#include <app/util/af.h>
#include <credentials/FabricTable.h>
#include <crypto/RandUtils.h>
#include <lib/core/CHIPTLV.h>
#include <lib/support/CHIPMemString.h>
#include <protocols/bdx/BdxUri.h>

#include <fstream>
#include <string.h>

using chip::BitFlags;
using chip::ByteSpan;
using chip::CharSpan;
using chip::FabricIndex;
using chip::FabricInfo;
using chip::MutableCharSpan;
using chip::NodeId;
using chip::Optional;
using chip::Server;
using chip::Span;
using chip::app::Clusters::OTAProviderDelegate;
using chip::bdx::TransferControlFlags;
using chip::Protocols::InteractionModel::Status;
using namespace chip;
using namespace chip::ota;
using namespace chip::app::Clusters::OtaSoftwareUpdateProvider;
using namespace chip::app::Clusters::OtaSoftwareUpdateProvider::Commands;

constexpr uint8_t kUpdateTokenLen    = 32;                      // must be between 8 and 32
constexpr uint8_t kUpdateTokenStrLen = kUpdateTokenLen * 2 + 1; // Hex string needs 2 hex chars for every byte
constexpr size_t kOtaHeaderMaxSize   = 1024;

// Arbitrary BDX Transfer Params
constexpr uint32_t kMaxBdxBlockSize                = 1024;
constexpr chip::System::Clock::Timeout kBdxTimeout = chip::System::Clock::Seconds16(5 * 60); // OTA Spec mandates >= 5 minutes
constexpr uint32_t kBdxServerPollIntervalMillis    = 50;                                     // poll every 50ms by default

void GetUpdateTokenString(const chip::ByteSpan & token, char * buf, size_t bufSize)
{
    const uint8_t * tokenData = static_cast<const uint8_t *>(token.data());
    size_t minLength          = chip::min(token.size(), bufSize);
    for (size_t i = 0; i < (minLength / 2) - 1; ++i)
    {
        snprintf(&buf[i * 2], bufSize, "%02X", tokenData[i]);
    }
}

void GenerateUpdateToken(uint8_t * buf, size_t bufSize)
{
    for (size_t i = 0; i < bufSize; ++i)
    {
        buf[i] = chip::Crypto::GetRandU8();
    }
}

OTAProviderExample::OTAProviderExample()
{
    memset(mOTAFilePath, 0, sizeof(mOTAFilePath));
    memset(mImageUri, 0, sizeof(mImageUri));
    mIgnoreQueryImageCount     = 0;
    mIgnoreApplyUpdateCount    = 0;
    mQueryImageStatus          = OTAQueryStatus::kNotAvailable;
    mUpdateAction              = OTAApplyUpdateAction::kDiscontinue;
    mDelayedQueryActionTimeSec = 0;
    mDelayedApplyActionTimeSec = 0;
    mUserConsentDelegate       = nullptr;
    mUserConsentNeeded         = false;
    mPollInterval              = kBdxServerPollIntervalMillis;
    mCandidates.clear();
}

void OTAProviderExample::SetOTAFilePath(const char * path)
{
    if (path != nullptr)
    {
        chip::Platform::CopyString(mOTAFilePath, path);
    }
    else
    {
        memset(mOTAFilePath, 0, sizeof(mOTAFilePath));
    }
}

void OTAProviderExample::SetImageUri(const char * imageUri)
{
    if (imageUri != nullptr)
    {
        chip::Platform::CopyString(mImageUri, imageUri);
    }
    else
    {
        memset(mImageUri, 0, sizeof(mImageUri));
    }
}

void OTAProviderExample::SetOTACandidates(std::vector<OTAProviderExample::DeviceSoftwareVersionModel> candidates)
{
    mCandidates = std::move(candidates);

    // Validate that each candidate matches the info in the image header
    for (auto candidate : mCandidates)
    {
        OTAImageHeaderParser parser;
        OTAImageHeader header;
        ParseOTAHeader(parser, candidate.otaURL, header);

        ChipLogDetail(SoftwareUpdate, "Validating image list candidate %s: ", candidate.otaURL);
        VerifyOrDie(candidate.vendorId == header.mVendorId);
        VerifyOrDie(candidate.productId == header.mProductId);
        VerifyOrDie(candidate.softwareVersion == header.mSoftwareVersion);
        VerifyOrDie(strlen(candidate.softwareVersionString) == header.mSoftwareVersionString.size());
        VerifyOrDie(memcmp(candidate.softwareVersionString, header.mSoftwareVersionString.data(),
                           header.mSoftwareVersionString.size()) == 0);
        if (header.mMinApplicableVersion.HasValue())
        {
            VerifyOrDie(candidate.minApplicableSoftwareVersion == header.mMinApplicableVersion.Value());
        }
        if (header.mMaxApplicableVersion.HasValue())
        {
            VerifyOrDie(candidate.maxApplicableSoftwareVersion == header.mMaxApplicableVersion.Value());
        }
        parser.Clear();
    }
}

static bool CompareSoftwareVersions(const OTAProviderExample::DeviceSoftwareVersionModel & a,
                                    const OTAProviderExample::DeviceSoftwareVersionModel & b)
{
    return (a.softwareVersion < b.softwareVersion);
}

bool OTAProviderExample::SelectOTACandidate(const uint16_t requestorVendorID, const uint16_t requestorProductID,
                                            const uint32_t requestorSoftwareVersion,
                                            OTAProviderExample::DeviceSoftwareVersionModel & finalCandidate)
{
    bool candidateFound = false;
    std::sort(mCandidates.begin(), mCandidates.end(), CompareSoftwareVersions);
    for (auto candidate : mCandidates)
    {
        // VendorID and ProductID will be the primary key when querying
        // the DCL servers. If not we can add the vendor/product ID checks here.
        if (candidate.softwareVersionValid && requestorSoftwareVersion < candidate.softwareVersion &&
            requestorSoftwareVersion >= candidate.minApplicableSoftwareVersion &&
            requestorSoftwareVersion <= candidate.maxApplicableSoftwareVersion)
        {
            candidateFound = true;
            finalCandidate = candidate;
        }
    }
    return candidateFound;
}

UserConsentSubject OTAProviderExample::GetUserConsentSubject(const app::CommandHandler * commandObj,
                                                             const app::ConcreteCommandPath & commandPath,
                                                             const QueryImage::DecodableType & commandData, uint32_t targetVersion)
{
    UserConsentSubject subject;
    subject.fabricIndex             = commandObj->GetSubjectDescriptor().fabricIndex;
    subject.requestorNodeId         = commandObj->GetSubjectDescriptor().subject;
    subject.providerEndpointId      = commandPath.mEndpointId;
    subject.requestorVendorId       = commandData.vendorId;
    subject.requestorProductId      = commandData.productId;
    subject.requestorCurrentVersion = commandData.softwareVersion;
    subject.requestorTargetVersion  = targetVersion;
    if (commandData.metadataForProvider.HasValue())
    {
        subject.metadata = commandData.metadataForProvider.Value();
    }
    return subject;
}

bool OTAProviderExample::ParseOTAHeader(OTAImageHeaderParser & parser, const char * otaFilePath, OTAImageHeader & header)
{
    uint8_t otaFileContent[kOtaHeaderMaxSize];
    ByteSpan buffer(otaFileContent);

    std::ifstream otaFile(otaFilePath, std::ifstream::in);
    if (!otaFile.is_open() || !otaFile.good())
    {
        ChipLogError(SoftwareUpdate, "Error opening OTA image file: %s", otaFilePath);
        return false;
    }

    otaFile.read(reinterpret_cast<char *>(otaFileContent), kOtaHeaderMaxSize);
    if (otaFile.bad())
    {
        ChipLogError(SoftwareUpdate, "Error reading OTA image file: %s", otaFilePath);
        return false;
    }

    parser.Init();
    if (!parser.IsInitialized())
    {
        return false;
    }

    CHIP_ERROR error = parser.AccumulateAndDecode(buffer, header);
    if (error != CHIP_NO_ERROR)
    {
        ChipLogError(SoftwareUpdate, "Error parsing OTA image header: %" CHIP_ERROR_FORMAT, error.Format());
        return false;
    }

    return true;
}

void OTAProviderExample::SendQueryImageResponse(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
                                                const QueryImage::DecodableType & commandData)
{
    VerifyOrReturn(commandObj != nullptr, ChipLogError(SoftwareUpdate, "Invalid commandObj, cannot send QueryImageResponse"));

    QueryImageResponse::Type response;
    bool requestorCanConsent             = commandData.requestorCanConsent.ValueOr(false);
    uint8_t updateToken[kUpdateTokenLen] = { 0 };
    char strBuf[kUpdateTokenStrLen]      = { 0 };

    // Set fields specific for an available status response
    if (mQueryImageStatus == OTAQueryStatus::kUpdateAvailable)
    {
        GenerateUpdateToken(updateToken, kUpdateTokenLen);
        GetUpdateTokenString(ByteSpan(updateToken), strBuf, kUpdateTokenStrLen);
        ChipLogDetail(SoftwareUpdate, "Generated updateToken: %s", strBuf);

        // TODO: This uses the current node as the provider to supply the OTA image. This can be configurable such that the
        // provider supplying the response is not the provider supplying the OTA image.
        FabricIndex fabricIndex       = commandObj->GetAccessingFabricIndex();
        const FabricInfo * fabricInfo = Server::GetInstance().GetFabricTable().FindFabricWithIndex(fabricIndex);
        NodeId nodeId                 = fabricInfo->GetPeerId().GetNodeId();

        // Generate the ImageURI if one is not already preset
        if (strlen(mImageUri) == 0)
        {
            // Only supporting BDX protocol for now
            MutableCharSpan uri(mImageUri);
            CHIP_ERROR error = chip::bdx::MakeURI(nodeId, CharSpan::fromCharString(mOTAFilePath), uri);
            if (error != CHIP_NO_ERROR)
            {
                ChipLogError(SoftwareUpdate, "Cannot generate URI");
                memset(mImageUri, 0, sizeof(mImageUri));
            }
            else
            {
                ChipLogDetail(SoftwareUpdate, "Generated URI: %s", mImageUri);
            }
        }

        // Initialize the transfer session in prepartion for a BDX transfer
        BitFlags<TransferControlFlags> bdxFlags;
        bdxFlags.Set(TransferControlFlags::kReceiverDrive);
        if (mBdxOtaSender.InitializeTransfer(commandObj->GetSubjectDescriptor().fabricIndex,
                                             commandObj->GetSubjectDescriptor().subject) == CHIP_NO_ERROR)
        {
            CHIP_ERROR error =
                mBdxOtaSender.PrepareForTransfer(&chip::DeviceLayer::SystemLayer(), chip::bdx::TransferRole::kSender, bdxFlags,
                                                 kMaxBdxBlockSize, kBdxTimeout, chip::System::Clock::Milliseconds32(mPollInterval));
            if (error != CHIP_NO_ERROR)
            {
                ChipLogError(SoftwareUpdate, "Cannot prepare for transfer: %" CHIP_ERROR_FORMAT, error.Format());
                commandObj->AddStatus(commandPath, Status::Failure);
                return;
            }

            response.imageURI.Emplace(chip::CharSpan::fromCharString(mImageUri));
            response.softwareVersion.Emplace(mSoftwareVersion);
            response.softwareVersionString.Emplace(chip::CharSpan::fromCharString(mSoftwareVersionString));
            response.updateToken.Emplace(chip::ByteSpan(updateToken));
        }
        else
        {
            // Another BDX transfer in progress
            mQueryImageStatus = OTAQueryStatus::kBusy;
        }
    }

    // Delay action time is only applicable when the provider is busy
    if (mQueryImageStatus == OTAQueryStatus::kBusy)
    {
        response.delayedActionTime.Emplace(mDelayedQueryActionTimeSec);
    }

    // Set remaining fields common to all status types
    response.status = mQueryImageStatus;
    if (mUserConsentNeeded && requestorCanConsent)
    {
        response.userConsentNeeded.Emplace(true);
    }
    else
    {
        response.userConsentNeeded.Emplace(false);
    }
    // For test coverage, sending empty metadata when (requestorNodeId % 2) == 0 and not sending otherwise.
    if (commandObj->GetSubjectDescriptor().subject % 2 == 0)
    {
        response.metadataForRequestor.Emplace(chip::ByteSpan());
    }

    // Either sends the response or an error status
    commandObj->AddResponse(commandPath, response);
}

void OTAProviderExample::HandleQueryImage(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
                                          const QueryImage::DecodableType & commandData)
{
    bool requestorCanConsent = commandData.requestorCanConsent.ValueOr(false);

    if (mIgnoreQueryImageCount > 0)
    {
        ChipLogDetail(SoftwareUpdate, "Skip sending QueryImageResponse, ignore count: %" PRIu32, mIgnoreQueryImageCount);
        mIgnoreQueryImageCount--;
        return;
    }

    if (mQueryImageStatus == OTAQueryStatus::kUpdateAvailable)
    {
        memset(mSoftwareVersionString, 0, sizeof(mSoftwareVersionString));

        if (!mCandidates.empty()) // If list of OTA candidates is supplied
        {
            OTAProviderExample::DeviceSoftwareVersionModel candidate;
            if (SelectOTACandidate(commandData.vendorId, commandData.productId, commandData.softwareVersion, candidate))
            {
                VerifyOrDie(sizeof(mSoftwareVersionString) > strlen(candidate.softwareVersionString));

                // This assumes all candidates have passed verification so the values are safe to use
                mSoftwareVersion = candidate.softwareVersion;
                memcpy(mSoftwareVersionString, candidate.softwareVersionString, strlen(candidate.softwareVersionString));
                SetOTAFilePath(candidate.otaURL);
            }
        }
        else if (strlen(mOTAFilePath) > 0) // If OTA file is directly provided
        {
            // Parse the header and set version info based on the header
            OTAImageHeaderParser parser;
            OTAImageHeader header;
            VerifyOrDie(ParseOTAHeader(parser, mOTAFilePath, header) == true);
            VerifyOrDie(sizeof(mSoftwareVersionString) > header.mSoftwareVersionString.size());
            mSoftwareVersion = header.mSoftwareVersion;
            memcpy(mSoftwareVersionString, header.mSoftwareVersionString.data(), header.mSoftwareVersionString.size());
            parser.Clear();
        }

        // If mUserConsentNeeded (set by the CLI) is true and requestor is capable of taking user consent
        // then delegate obtaining user consent to the requestor
        if (mUserConsentDelegate && (requestorCanConsent && mUserConsentNeeded) == false)
        {
            UserConsentState state = mUserConsentDelegate->GetUserConsentState(
                GetUserConsentSubject(commandObj, commandPath, commandData, mSoftwareVersion));
            ChipLogProgress(SoftwareUpdate, "User Consent state: %s", mUserConsentDelegate->UserConsentStateToString(state));
            switch (state)
            {
            case UserConsentState::kGranted:
                mQueryImageStatus = OTAQueryStatus::kUpdateAvailable;
                break;

            case UserConsentState::kObtaining:
                mQueryImageStatus = OTAQueryStatus::kBusy;
                break;

            case UserConsentState::kDenied:
            case UserConsentState::kUnknown:
                mQueryImageStatus = OTAQueryStatus::kNotAvailable;
                break;
            }
        }
    }

    // Guarantees that either a response or an error status is sent
    SendQueryImageResponse(commandObj, commandPath, commandData);

    // After the first response is sent, default to these values for subsequent queries
    mQueryImageStatus          = OTAQueryStatus::kUpdateAvailable;
    mDelayedQueryActionTimeSec = 0;
}

void OTAProviderExample::HandleApplyUpdateRequest(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
                                                  const ApplyUpdateRequest::DecodableType & commandData)
{
    VerifyOrReturn(commandObj != nullptr, ChipLogError(SoftwareUpdate, "Invalid commandObj, cannot handle ApplyUpdateRequest"));

    if (mIgnoreApplyUpdateCount > 0)
    {
        ChipLogDetail(SoftwareUpdate, "Skip sending ApplyUpdateResponse, ignore count %" PRIu32, mIgnoreApplyUpdateCount);
        mIgnoreApplyUpdateCount--;
        return;
    }

    // TODO: handle multiple transfers by tracking updateTokens
    char tokenBuf[kUpdateTokenStrLen] = { 0 };

    GetUpdateTokenString(commandData.updateToken, tokenBuf, kUpdateTokenStrLen);
    ChipLogDetail(SoftwareUpdate, "%s: token: %s, version: %" PRIu32, __FUNCTION__, tokenBuf, commandData.newVersion);

    ApplyUpdateResponse::Type response;
    response.action            = mUpdateAction;
    response.delayedActionTime = mDelayedApplyActionTimeSec;

    // Reset delay back to 0 for subsequent uses
    mDelayedApplyActionTimeSec = 0;
    // Reset back to success case for subsequent uses
    mUpdateAction = OTAApplyUpdateAction::kProceed;

    // Either sends the response or an error status
    commandObj->AddResponse(commandPath, response);
}

void OTAProviderExample::HandleNotifyUpdateApplied(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
                                                   const NotifyUpdateApplied::DecodableType & commandData)
{
    VerifyOrReturn(commandObj != nullptr, ChipLogError(SoftwareUpdate, "Invalid commandObj, cannot handle NotifyUpdateApplied"));

    char tokenBuf[kUpdateTokenStrLen] = { 0 };

    GetUpdateTokenString(commandData.updateToken, tokenBuf, kUpdateTokenStrLen);
    ChipLogDetail(SoftwareUpdate, "%s: token: %s, version: %" PRIu32, __FUNCTION__, tokenBuf, commandData.softwareVersion);

    commandObj->AddStatus(commandPath, Status::Success);
}
