/*
 *
 *    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 <controller/CurrentFabricRemover.h>

#include <app-common/zap-generated/cluster-objects.h>

using namespace chip::app::Clusters;

namespace chip {
namespace Controller {

CHIP_ERROR CurrentFabricRemover::RemoveCurrentFabric(NodeId remoteNodeId, Callback::Callback<OnCurrentFabricRemove> * callback)
{
    mRemoteNodeId                = remoteNodeId;
    mCurrentFabricRemoveCallback = callback;
    mNextStep                    = Step::kReadCurrentFabricIndex;

    return mController->GetConnectedDevice(remoteNodeId, &mOnDeviceConnectedCallback, &mOnDeviceConnectionFailureCallback);
}

CHIP_ERROR CurrentFabricRemover::ReadCurrentFabricIndex(Messaging::ExchangeManager & exchangeMgr,
                                                        const SessionHandle & sessionHandle)
{
    using TypeInfo = OperationalCredentials::Attributes::CurrentFabricIndex::TypeInfo;
    ClusterBase cluster(exchangeMgr, sessionHandle, kRootEndpointId);

    return cluster.ReadAttribute<TypeInfo>(this, OnSuccessReadCurrentFabricIndex, OnReadAttributeFailure);
}

CHIP_ERROR CurrentFabricRemover::SendRemoveFabricIndex(Messaging::ExchangeManager & exchangeMgr,
                                                       const SessionHandle & sessionHandle)
{
    if (mFabricIndex == kUndefinedFabricIndex)
    {
        return CHIP_ERROR_INVALID_FABRIC_INDEX;
    }

    OperationalCredentials::Commands::RemoveFabric::Type request;
    request.fabricIndex = mFabricIndex;

    ClusterBase cluster(exchangeMgr, sessionHandle, 0);

    return cluster.InvokeCommand(request, this, OnSuccessRemoveFabric, OnCommandFailure);
}

void CurrentFabricRemover::OnDeviceConnectedFn(void * context, Messaging::ExchangeManager & exchangeMgr,
                                               const SessionHandle & sessionHandle)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    auto * self    = static_cast<CurrentFabricRemover *>(context);
    VerifyOrReturn(self != nullptr, ChipLogProgress(Controller, "Device connected callback with null context. Ignoring"));

    switch (self->mNextStep)
    {
    case Step::kReadCurrentFabricIndex: {
        err = self->ReadCurrentFabricIndex(exchangeMgr, sessionHandle);
        break;
    }
    case Step::kSendRemoveFabric: {
        err = self->SendRemoveFabricIndex(exchangeMgr, sessionHandle);
        break;
    }
    default:
        err = CHIP_ERROR_INCORRECT_STATE;
        break;
    }

    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(Controller, "Current Fabric Remover failure : %" CHIP_ERROR_FORMAT, err.Format());
        FinishRemoveCurrentFabric(context, err);
    }
}

void CurrentFabricRemover::OnDeviceConnectionFailureFn(void * context, const ScopedNodeId & peerId, CHIP_ERROR err)
{
    ChipLogProgress(Controller, "OnDeviceConnectionFailureFn: %" CHIP_ERROR_FORMAT, err.Format());

    auto * self = static_cast<CurrentFabricRemover *>(context);
    VerifyOrReturn(self != nullptr, ChipLogProgress(Controller, "Device connected failure callback with null context. Ignoring"));

    FinishRemoveCurrentFabric(context, err);
}

void CurrentFabricRemover::OnSuccessReadCurrentFabricIndex(void * context, FabricIndex fabricIndex)
{
    auto * self = static_cast<CurrentFabricRemover *>(context);
    VerifyOrReturn(self != nullptr,
                   ChipLogProgress(Controller, "Success Read Current Fabric index callback with null context. Ignoring"));
    self->mFabricIndex = fabricIndex;
    self->mNextStep    = Step::kSendRemoveFabric;
    CHIP_ERROR err     = self->mController->GetConnectedDevice(self->mRemoteNodeId, &self->mOnDeviceConnectedCallback,
                                                               &self->mOnDeviceConnectionFailureCallback);
    if (err != CHIP_NO_ERROR)
    {
        FinishRemoveCurrentFabric(context, err);
    }
}

void CurrentFabricRemover::OnReadAttributeFailure(void * context, CHIP_ERROR err)
{
    ChipLogProgress(Controller, "OnReadAttributeFailure %" CHIP_ERROR_FORMAT, err.Format());

    auto * self = static_cast<CurrentFabricRemover *>(context);
    VerifyOrReturn(self != nullptr, ChipLogProgress(Controller, "Read Attribute failure callback with null context. Ignoring"));

    FinishRemoveCurrentFabric(context, err);
}

void CurrentFabricRemover::OnSuccessRemoveFabric(void * context,
                                                 const OperationalCredentials::Commands::NOCResponse::DecodableType & data)
{
    auto * self = static_cast<CurrentFabricRemover *>(context);
    VerifyOrReturn(self != nullptr,
                   ChipLogProgress(Controller, "Success Remove Fabric command callback with null context. Ignoring"));

    FinishRemoveCurrentFabric(context, CHIP_NO_ERROR);
}

void CurrentFabricRemover::OnCommandFailure(void * context, CHIP_ERROR err)
{
    ChipLogProgress(Controller, "OnCommandFailure %" CHIP_ERROR_FORMAT, err.Format());

    auto * self = static_cast<CurrentFabricRemover *>(context);
    VerifyOrReturn(self != nullptr, ChipLogProgress(Controller, "Send command failure callback with null context. Ignoring"));

    FinishRemoveCurrentFabric(context, err);
}

void CurrentFabricRemover::FinishRemoveCurrentFabric(void * context, CHIP_ERROR err)
{
    ChipLogError(Controller, "Remove Current Fabric Result : %" CHIP_ERROR_FORMAT, err.Format());
    auto * self     = static_cast<CurrentFabricRemover *>(context);
    self->mNextStep = Step::kAcceptRemoveFabricStart;
    if (self->mCurrentFabricRemoveCallback != nullptr)
    {
        self->mCurrentFabricRemoveCallback->mCall(self->mCurrentFabricRemoveCallback->mContext, self->mRemoteNodeId, err);
    }
}

AutoCurrentFabricRemover::AutoCurrentFabricRemover(DeviceController * controller) :
    CurrentFabricRemover(controller), mOnRemoveCurrentFabricCallback(OnRemoveCurrentFabric, this)
{}

CHIP_ERROR AutoCurrentFabricRemover::RemoveCurrentFabric(DeviceController * controller, NodeId remoteNodeId)
{
    // Not using Platform::New because we want to keep our constructor private.
    auto * remover = new (std::nothrow) AutoCurrentFabricRemover(controller);
    if (remover == nullptr)
    {
        return CHIP_ERROR_NO_MEMORY;
    }

    CHIP_ERROR err = remover->CurrentFabricRemover::RemoveCurrentFabric(remoteNodeId, &remover->mOnRemoveCurrentFabricCallback);
    if (err != CHIP_NO_ERROR)
    {
        delete remover;
    }
    // Else will clean up when the callback is called.
    return err;
}

void AutoCurrentFabricRemover::OnRemoveCurrentFabric(void * context, NodeId remoteNodeId, CHIP_ERROR status)
{
    auto * self = static_cast<AutoCurrentFabricRemover *>(context);
    delete self;
}
} // namespace Controller
} // namespace chip
