/*
 *    Copyright (c) 2022 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 <app-common/zap-generated/cluster-objects.h>
#include <controller/CommissioningWindowOpener.h>
#include <lib/core/CHIPSafeCasts.h>
#include <lib/support/CHIPMem.h>
#include <protocols/secure_channel/PASESession.h>
#include <setup_payload/ManualSetupPayloadGenerator.h>
#include <setup_payload/QRCodeSetupPayloadGenerator.h>

using namespace chip::app::Clusters;
using namespace chip::System::Clock;
using namespace chip::Crypto;

namespace {
// TODO: What should the timed invoke timeout here be?
constexpr uint16_t kTimedInvokeTimeoutMs = 10000;
} // anonymous namespace

namespace chip {
namespace Controller {

CHIP_ERROR CommissioningWindowOpener::OpenBasicCommissioningWindow(NodeId deviceId, Seconds16 timeout,
                                                                   Callback::Callback<OnOpenBasicCommissioningWindow> * callback)
{
    VerifyOrReturnError(mNextStep == Step::kAcceptCommissioningStart, CHIP_ERROR_INCORRECT_STATE);
    mSetupPayload = SetupPayload();

    // Basic commissioning does not use the setup payload.

    mCommissioningWindowOption           = CommissioningWindowOption::kOriginalSetupCode;
    mBasicCommissioningWindowCallback    = callback;
    mCommissioningWindowCallback         = nullptr;
    mCommissioningWindowVerifierCallback = nullptr;
    mNodeId                              = deviceId;
    mCommissioningWindowTimeout          = timeout;

    mNextStep = Step::kOpenCommissioningWindow;
    return mController->GetConnectedDevice(mNodeId, &mDeviceConnected, &mDeviceConnectionFailure);
}

CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindow(NodeId deviceId, Seconds16 timeout, uint32_t iteration,
                                                              uint16_t discriminator, Optional<uint32_t> setupPIN,
                                                              Optional<ByteSpan> salt,
                                                              Callback::Callback<OnOpenCommissioningWindow> * callback,
                                                              SetupPayload & payload, bool readVIDPIDAttributes)
{
    return OpenCommissioningWindow(CommissioningWindowPasscodeParams()
                                       .SetNodeId(deviceId)
                                       .SetTimeout(timeout)
                                       .SetIteration(iteration)
                                       .SetDiscriminator(discriminator)
                                       .SetSetupPIN(setupPIN)
                                       .SetSalt(salt)
                                       .SetReadVIDPIDAttributes(readVIDPIDAttributes)
                                       .SetCallback(callback),
                                   payload);
}

CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindow(const CommissioningWindowPasscodeParams & params,
                                                              SetupPayload & payload)
{
    VerifyOrReturnError(mNextStep == Step::kAcceptCommissioningStart, CHIP_ERROR_INCORRECT_STATE);
    VerifyOrReturnError(params.HasNodeId(), CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(params.HasDiscriminator(), CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(kSpake2p_Min_PBKDF_Iterations <= params.GetIteration() &&
                            params.GetIteration() <= kSpake2p_Max_PBKDF_Iterations,
                        CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(!params.HasSalt() ||
                            (params.GetSalt().size() >= kSpake2p_Min_PBKDF_Salt_Length &&
                             params.GetSalt().size() <= kSpake2p_Max_PBKDF_Salt_Length),
                        CHIP_ERROR_INVALID_ARGUMENT);

    mSetupPayload = SetupPayload();

    if (params.HasSetupPIN())
    {
        VerifyOrReturnError(SetupPayload::IsValidSetupPIN(params.GetSetupPIN()), CHIP_ERROR_INVALID_ARGUMENT);
        mCommissioningWindowOption = CommissioningWindowOption::kTokenWithProvidedPIN;
        mSetupPayload.setUpPINCode = params.GetSetupPIN();
    }
    else
    {
        mCommissioningWindowOption = CommissioningWindowOption::kTokenWithRandomPIN;
    }

    mSetupPayload.version = 0;
    mDiscriminator.SetLongValue(params.GetDiscriminator());
    mSetupPayload.discriminator = mDiscriminator;
    mSetupPayload.rendezvousInformation.SetValue(RendezvousInformationFlag::kOnNetwork);

    if (params.HasSalt())
    {
        memcpy(mPBKDFSaltBuffer, params.GetSalt().data(), params.GetSalt().size());
        mPBKDFSalt = ByteSpan(mPBKDFSaltBuffer, params.GetSalt().size());
    }
    else
    {
        ReturnErrorOnFailure(DRBG_get_bytes(mPBKDFSaltBuffer, sizeof(mPBKDFSaltBuffer)));
        mPBKDFSalt = ByteSpan(mPBKDFSaltBuffer);
    }
    mPBKDFIterations = params.GetIteration();

    bool randomSetupPIN = !params.HasSetupPIN();
    ReturnErrorOnFailure(
        PASESession::GeneratePASEVerifier(mVerifier, mPBKDFIterations, mPBKDFSalt, randomSetupPIN, mSetupPayload.setUpPINCode));

    payload                              = mSetupPayload;
    mCommissioningWindowCallback         = params.GetCallback();
    mBasicCommissioningWindowCallback    = nullptr;
    mCommissioningWindowVerifierCallback = nullptr;
    mNodeId                              = params.GetNodeId();
    mCommissioningWindowTimeout          = params.GetTimeout();
    mTargetEndpointId                    = params.GetEndpointId();

    if (params.GetReadVIDPIDAttributes())
    {
        mNextStep = Step::kReadVID;
    }
    else
    {
        mNextStep = Step::kOpenCommissioningWindow;
    }

    return mController->GetConnectedDevice(mNodeId, &mDeviceConnected, &mDeviceConnectionFailure);
}

CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindow(const CommissioningWindowVerifierParams & params)
{
    VerifyOrReturnError(mNextStep == Step::kAcceptCommissioningStart, CHIP_ERROR_INCORRECT_STATE);
    VerifyOrReturnError(params.HasNodeId(), CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(params.HasDiscriminator(), CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(kSpake2p_Min_PBKDF_Iterations <= params.GetIteration() &&
                            params.GetIteration() <= kSpake2p_Max_PBKDF_Iterations,
                        CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(params.GetSalt().size() >= kSpake2p_Min_PBKDF_Salt_Length &&
                            params.GetSalt().size() <= kSpake2p_Max_PBKDF_Salt_Length,
                        CHIP_ERROR_INVALID_ARGUMENT);
    memcpy(mPBKDFSaltBuffer, params.GetSalt().data(), params.GetSalt().size());
    mPBKDFSalt = ByteSpan(mPBKDFSaltBuffer, params.GetSalt().size());

    ReturnErrorOnFailure(mVerifier.Deserialize(params.GetVerifier()));
    mCommissioningWindowVerifierCallback = params.GetCallback();
    mBasicCommissioningWindowCallback    = nullptr;
    mCommissioningWindowCallback         = nullptr;
    mNodeId                              = params.GetNodeId();
    mCommissioningWindowTimeout          = params.GetTimeout();
    mPBKDFIterations                     = params.GetIteration();
    mCommissioningWindowOption           = CommissioningWindowOption::kTokenWithProvidedPIN;
    mDiscriminator.SetLongValue(params.GetDiscriminator());
    mTargetEndpointId = params.GetEndpointId();

    mNextStep = Step::kOpenCommissioningWindow;

    return mController->GetConnectedDevice(mNodeId, &mDeviceConnected, &mDeviceConnectionFailure);
}

CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindowInternal(Messaging::ExchangeManager & exchangeMgr,
                                                                      const SessionHandle & sessionHandle)
{
    ChipLogProgress(Controller, "OpenCommissioningWindow for device ID 0x" ChipLogFormatX64, ChipLogValueX64(mNodeId));

    ClusterBase cluster(exchangeMgr, sessionHandle, mTargetEndpointId);

    if (mCommissioningWindowOption != CommissioningWindowOption::kOriginalSetupCode)
    {
        Spake2pVerifierSerialized serializedVerifier;
        MutableByteSpan serializedVerifierSpan(serializedVerifier);
        ReturnErrorOnFailure(mVerifier.Serialize(serializedVerifierSpan));

        AdministratorCommissioning::Commands::OpenCommissioningWindow::Type request;
        request.commissioningTimeout = mCommissioningWindowTimeout.count();
        request.PAKEPasscodeVerifier = serializedVerifierSpan;
        request.discriminator        = mDiscriminator.GetLongValue();
        request.iterations           = mPBKDFIterations;
        request.salt                 = mPBKDFSalt;

        ReturnErrorOnFailure(cluster.InvokeCommand(request, this, OnOpenCommissioningWindowSuccess,
                                                   OnOpenCommissioningWindowFailure, MakeOptional(kTimedInvokeTimeoutMs)));
    }
    else
    {
        AdministratorCommissioning::Commands::OpenBasicCommissioningWindow::Type request;
        request.commissioningTimeout = mCommissioningWindowTimeout.count();
        ReturnErrorOnFailure(cluster.InvokeCommand(request, this, OnOpenCommissioningWindowSuccess,
                                                   OnOpenCommissioningWindowFailure, MakeOptional(kTimedInvokeTimeoutMs)));
    }

    return CHIP_NO_ERROR;
}

void CommissioningWindowOpener::OnPIDReadResponse(void * context, uint16_t value)
{
    ChipLogProgress(Controller, "Received PID for the device. Value %d", value);
    auto * self                   = static_cast<CommissioningWindowOpener *>(context);
    self->mSetupPayload.productID = value;

    self->mNextStep = Step::kOpenCommissioningWindow;

    CHIP_ERROR err = self->mController->GetConnectedDevice(self->mNodeId, &self->mDeviceConnected, &self->mDeviceConnectionFailure);
    if (err != CHIP_NO_ERROR)
    {
        OnOpenCommissioningWindowFailure(context, err);
    }
}

void CommissioningWindowOpener::OnVIDReadResponse(void * context, VendorId value)
{
    ChipLogProgress(Controller, "Received VID for the device. Value %d", to_underlying(value));

    auto * self = static_cast<CommissioningWindowOpener *>(context);

    self->mSetupPayload.vendorID = value;

    self->mNextStep = Step::kReadPID;
    CHIP_ERROR err = self->mController->GetConnectedDevice(self->mNodeId, &self->mDeviceConnected, &self->mDeviceConnectionFailure);
    if (err != CHIP_NO_ERROR)
    {
        OnOpenCommissioningWindowFailure(context, err);
    }
}

void CommissioningWindowOpener::OnVIDPIDReadFailureResponse(void * context, CHIP_ERROR error)
{
    ChipLogProgress(Controller, "Failed to read VID/PID for the device. error %" CHIP_ERROR_FORMAT, error.Format());
    OnOpenCommissioningWindowFailure(context, error);
}

void CommissioningWindowOpener::OnOpenCommissioningWindowSuccess(void * context, const chip::app::DataModel::NullObjectType &)
{
    ChipLogProgress(Controller, "Successfully opened pairing window on the device");
    auto * self     = static_cast<CommissioningWindowOpener *>(context);
    self->mNextStep = Step::kAcceptCommissioningStart;
    if (self->mCommissioningWindowCallback != nullptr)
    {
        char payloadBuffer[QRCodeBasicSetupPayloadGenerator::kMaxQRCodeBase38RepresentationLength + 1];

        MutableCharSpan manualCode(payloadBuffer);
        CHIP_ERROR err = ManualSetupPayloadGenerator(self->mSetupPayload).payloadDecimalStringRepresentation(manualCode);
        if (err == CHIP_NO_ERROR)
        {
            ChipLogProgress(Controller, "Manual pairing code: [%s]", payloadBuffer);
        }
        else
        {
            ChipLogError(Controller, "Unable to generate manual code for setup payload: %" CHIP_ERROR_FORMAT, err.Format());
        }

        MutableCharSpan QRCode(payloadBuffer);
        err = QRCodeBasicSetupPayloadGenerator(self->mSetupPayload).payloadBase38Representation(QRCode);
        if (err == CHIP_NO_ERROR)
        {
            ChipLogProgress(Controller, "SetupQRCode: [%s]", payloadBuffer);
        }
        else
        {
            ChipLogError(Controller, "Unable to generate QR code for setup payload: %" CHIP_ERROR_FORMAT, err.Format());
        }

        self->mCommissioningWindowCallback->mCall(self->mCommissioningWindowCallback->mContext, self->mNodeId, CHIP_NO_ERROR,
                                                  self->mSetupPayload);
        // Don't touch `self` anymore; it might have been destroyed by the callee.
    }
    else if (self->mCommissioningWindowVerifierCallback != nullptr)
    {
        self->mCommissioningWindowVerifierCallback->mCall(self->mCommissioningWindowVerifierCallback->mContext, self->mNodeId,
                                                          CHIP_NO_ERROR);
        // Don't touch `self` anymore; it might have been destroyed by the callee.
    }
    else if (self->mBasicCommissioningWindowCallback != nullptr)
    {
        self->mBasicCommissioningWindowCallback->mCall(self->mBasicCommissioningWindowCallback->mContext, self->mNodeId,
                                                       CHIP_NO_ERROR);
        // Don't touch `self` anymore; it might have been destroyed by the callee.
    }
}

void CommissioningWindowOpener::OnOpenCommissioningWindowFailure(void * context, CHIP_ERROR error)
{
    ChipLogError(Controller, "Failed to open pairing window on the device. Status %" CHIP_ERROR_FORMAT, error.Format());
    auto * self     = static_cast<CommissioningWindowOpener *>(context);
    self->mNextStep = Step::kAcceptCommissioningStart;
    if (self->mCommissioningWindowCallback != nullptr)
    {
        self->mCommissioningWindowCallback->mCall(self->mCommissioningWindowCallback->mContext, self->mNodeId, error,
                                                  SetupPayload());
    }
    else if (self->mCommissioningWindowVerifierCallback != nullptr)
    {
        self->mCommissioningWindowVerifierCallback->mCall(self->mCommissioningWindowVerifierCallback->mContext, self->mNodeId,
                                                          error);
    }
    else if (self->mBasicCommissioningWindowCallback != nullptr)
    {
        self->mBasicCommissioningWindowCallback->mCall(self->mBasicCommissioningWindowCallback->mContext, self->mNodeId, error);
    }
}

void CommissioningWindowOpener::OnDeviceConnectedCallback(void * context, Messaging::ExchangeManager & exchangeMgr,
                                                          const SessionHandle & sessionHandle)
{
    auto * self = static_cast<CommissioningWindowOpener *>(context);

#if CHIP_ERROR_LOGGING
    const char * messageIfError = nullptr;
#endif // CHIP_ERROR_LOGGING
    CHIP_ERROR err = CHIP_NO_ERROR;

    switch (self->mNextStep)
    {
    case Step::kReadVID: {
        ClusterBase cluster(exchangeMgr, sessionHandle, kRootEndpointId);
        err = cluster.ReadAttribute<BasicInformation::Attributes::VendorID::TypeInfo>(context, OnVIDReadResponse,
                                                                                      OnVIDPIDReadFailureResponse);
#if CHIP_ERROR_LOGGING
        messageIfError = "Could not read VID for opening commissioning window";
#endif // CHIP_ERROR_LOGGING
        break;
    }
    case Step::kReadPID: {
        ClusterBase cluster(exchangeMgr, sessionHandle, kRootEndpointId);
        err = cluster.ReadAttribute<BasicInformation::Attributes::ProductID::TypeInfo>(context, OnPIDReadResponse,
                                                                                       OnVIDPIDReadFailureResponse);
#if CHIP_ERROR_LOGGING
        messageIfError = "Could not read PID for opening commissioning window";
#endif // CHIP_ERROR_LOGGING
        break;
    }
    case Step::kOpenCommissioningWindow: {
        err = self->OpenCommissioningWindowInternal(exchangeMgr, sessionHandle);
#if CHIP_ERROR_LOGGING
        messageIfError = "Could not connect to open commissioning window";
#endif // CHIP_ERROR_LOGGING
        break;
    }
    case Step::kAcceptCommissioningStart: {
        err = CHIP_ERROR_INCORRECT_STATE;
#if CHIP_ERROR_LOGGING
        messageIfError = "Just got a connected device; how can we be done?";
#endif // CHIP_ERROR_LOGGING
        break;
    }
    }

    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(Controller, "%s: %" CHIP_ERROR_FORMAT, messageIfError, err.Format());
        OnOpenCommissioningWindowFailure(context, err);
    }
}

void CommissioningWindowOpener::OnDeviceConnectionFailureCallback(void * context, const ScopedNodeId & peerId, CHIP_ERROR error)
{
    OnOpenCommissioningWindowFailure(context, error);
}

AutoCommissioningWindowOpener::AutoCommissioningWindowOpener(DeviceController * controller) :
    CommissioningWindowOpener(controller), mOnOpenCommissioningWindowCallback(OnOpenCommissioningWindowResponse, this),
    mOnOpenBasicCommissioningWindowCallback(OnOpenBasicCommissioningWindowResponse, this)
{}

CHIP_ERROR AutoCommissioningWindowOpener::OpenBasicCommissioningWindow(DeviceController * controller, NodeId deviceId,
                                                                       Seconds16 timeout)
{
    // Not using Platform::New because we want to keep our constructor private.
    auto * opener = new (std::nothrow) AutoCommissioningWindowOpener(controller);
    if (opener == nullptr)
    {
        return CHIP_ERROR_NO_MEMORY;
    }

    CHIP_ERROR err = opener->CommissioningWindowOpener::OpenBasicCommissioningWindow(
        deviceId, timeout, &opener->mOnOpenBasicCommissioningWindowCallback);
    if (err != CHIP_NO_ERROR)
    {
        delete opener;
    }
    // Else will clean up when the callback is called.
    return err;
}

CHIP_ERROR AutoCommissioningWindowOpener::OpenCommissioningWindow(DeviceController * controller, NodeId deviceId, Seconds16 timeout,
                                                                  uint32_t iteration, uint16_t discriminator,
                                                                  Optional<uint32_t> setupPIN, Optional<ByteSpan> salt,
                                                                  SetupPayload & payload, bool readVIDPIDAttributes)
{
    // Not using Platform::New because we want to keep our constructor private.
    auto * opener = new (std::nothrow) AutoCommissioningWindowOpener(controller);
    if (opener == nullptr)
    {
        return CHIP_ERROR_NO_MEMORY;
    }

    CHIP_ERROR err = opener->CommissioningWindowOpener::OpenCommissioningWindow(
        deviceId, timeout, iteration, discriminator, setupPIN, salt, &opener->mOnOpenCommissioningWindowCallback, payload,
        readVIDPIDAttributes);
    if (err != CHIP_NO_ERROR)
    {
        delete opener;
    }
    // Else will clean up when the callback is called.
    return err;
}

void AutoCommissioningWindowOpener::OnOpenCommissioningWindowResponse(void * context, NodeId deviceId, CHIP_ERROR status,
                                                                      chip::SetupPayload payload)
{
    auto * self = static_cast<AutoCommissioningWindowOpener *>(context);
    delete self;
}
void AutoCommissioningWindowOpener::OnOpenBasicCommissioningWindowResponse(void * context, NodeId deviceId, CHIP_ERROR status)
{
    auto * self = static_cast<AutoCommissioningWindowOpener *>(context);
    delete self;
}

} // namespace Controller
} // namespace chip
