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

/**
 *    @file
 *      This file defines the initiator side of a CHIP Write Interaction.
 *
 */

#include "lib/core/CHIPError.h"
#include <app/AppConfig.h>
#include <app/InteractionModelEngine.h>
#include <app/TimedRequest.h>
#include <app/WriteClient.h>

namespace chip {
namespace app {

void WriteClient::Close()
{
    MoveToState(State::AwaitingDestruction);

    if (mpCallback)
    {
        mpCallback->OnDone(this);
    }
}

CHIP_ERROR WriteClient::ProcessWriteResponseMessage(System::PacketBufferHandle && payload)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    System::PacketBufferTLVReader reader;
    TLV::TLVReader attributeStatusesReader;
    WriteResponseMessage::Parser writeResponse;
    AttributeStatusIBs::Parser attributeStatusesParser;

    reader.Init(std::move(payload));

    ReturnErrorOnFailure(writeResponse.Init(reader));

#if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
    ReturnErrorOnFailure(writeResponse.CheckSchemaValidity());
#endif

    err = writeResponse.GetWriteResponses(&attributeStatusesParser);
    if (err == CHIP_END_OF_TLV)
    {
        return CHIP_NO_ERROR;
    }
    ReturnErrorOnFailure(err);

    attributeStatusesParser.GetReader(&attributeStatusesReader);

    while (CHIP_NO_ERROR == (err = attributeStatusesReader.Next()))
    {
        VerifyOrReturnError(TLV::AnonymousTag() == attributeStatusesReader.GetTag(), err = CHIP_ERROR_INVALID_TLV_TAG);

        AttributeStatusIB::Parser element;

        ReturnErrorOnFailure(element.Init(attributeStatusesReader));
        ReturnErrorOnFailure(ProcessAttributeStatusIB(element));
    }

    // if we have exhausted this container
    if (CHIP_END_OF_TLV == err)
    {
        err = CHIP_NO_ERROR;
    }
    ReturnErrorOnFailure(err);
    return writeResponse.ExitContainer();
}

CHIP_ERROR WriteClient::PrepareAttributeIB(const ConcreteDataAttributePath & aPath)
{
    AttributeDataIBs::Builder & writeRequests  = mWriteRequestBuilder.GetWriteRequests();
    AttributeDataIB::Builder & attributeDataIB = writeRequests.CreateAttributeDataIBBuilder();
    ReturnErrorOnFailure(writeRequests.GetError());
    if (aPath.mDataVersion.HasValue())
    {
        attributeDataIB.DataVersion(aPath.mDataVersion.Value());
        mHasDataVersion = true;
    }
    ReturnErrorOnFailure(attributeDataIB.GetError());
    AttributePathIB::Builder & path = attributeDataIB.CreatePath();

    // We are using kInvalidEndpointId just for group write requests. This is not the correct use of ConcreteDataAttributePath.
    // TODO: update AttributePathParams or ConcreteDataAttributePath for a class supports both nullable list index and missing
    // endpoint id.
    if (aPath.mEndpointId != kInvalidEndpointId)
    {
        path.Endpoint(aPath.mEndpointId);
    }
    path.Cluster(aPath.mClusterId).Attribute(aPath.mAttributeId);
    if (aPath.IsListItemOperation())
    {
        if (aPath.mListOp == ConcreteDataAttributePath::ListOperation::AppendItem)
        {
            path.ListIndex(DataModel::NullNullable);
        }
        else
        {
            // We do not support other list operations (i.e. update, delete etc) for now.
            return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
        }
    }
    ReturnErrorOnFailure(path.EndOfAttributePathIB().GetError());

    return CHIP_NO_ERROR;
}

CHIP_ERROR WriteClient::FinishAttributeIB()
{
    AttributeDataIB::Builder & attributeDataIB = mWriteRequestBuilder.GetWriteRequests().GetAttributeDataIBBuilder();
    attributeDataIB.EndOfAttributeDataIB();
    ReturnErrorOnFailure(attributeDataIB.GetError());
    MoveToState(State::AddAttribute);
    return CHIP_NO_ERROR;
}

TLV::TLVWriter * WriteClient::GetAttributeDataIBTLVWriter()
{
    return mWriteRequestBuilder.GetWriteRequests().GetAttributeDataIBBuilder().GetWriter();
}

CHIP_ERROR WriteClient::FinalizeMessage(bool aHasMoreChunks)
{
    System::PacketBufferHandle packet;
    VerifyOrReturnError(mState == State::AddAttribute, CHIP_ERROR_INCORRECT_STATE);

    TLV::TLVWriter * writer = mWriteRequestBuilder.GetWriter();
    ReturnErrorCodeIf(writer == nullptr, CHIP_ERROR_INCORRECT_STATE);
    ReturnErrorOnFailure(writer->UnreserveBuffer(kReservedSizeForTLVEncodingOverhead));

    AttributeDataIBs::Builder & attributeDataIBsBuilder = mWriteRequestBuilder.GetWriteRequests().EndOfAttributeDataIBs();
    ReturnErrorOnFailure(attributeDataIBsBuilder.GetError());

    mWriteRequestBuilder.MoreChunkedMessages(aHasMoreChunks).EndOfWriteRequestMessage();
    ReturnErrorOnFailure(mWriteRequestBuilder.GetError());
    ReturnErrorOnFailure(mMessageWriter.Finalize(&packet));
    mChunks.AddToEnd(std::move(packet));
    return CHIP_NO_ERROR;
}

CHIP_ERROR WriteClient::EnsureMessage()
{
    if (mState != State::AddAttribute)
    {
        return StartNewMessage();
    }
    return CHIP_NO_ERROR;
}

CHIP_ERROR WriteClient::StartNewMessage()
{
    uint16_t reservedSize = 0;

    if (mState == State::AddAttribute)
    {
        ReturnErrorOnFailure(FinalizeMessage(true));
    }

    // Do not allow timed request with chunks.
    VerifyOrReturnError(!(mTimedWriteTimeoutMs.HasValue() && !mChunks.IsNull()), CHIP_ERROR_NO_MEMORY);

    System::PacketBufferHandle packet = System::PacketBufferHandle::New(kMaxSecureSduLengthBytes);
    VerifyOrReturnError(!packet.IsNull(), CHIP_ERROR_NO_MEMORY);

    // Always limit the size of the packet to fit within kMaxSecureSduLengthBytes regardless of the available buffer capacity.
    if (packet->AvailableDataLength() > kMaxSecureSduLengthBytes)
    {
        reservedSize = static_cast<uint16_t>(packet->AvailableDataLength() - kMaxSecureSduLengthBytes);
    }

    // ... and we need to reserve some extra space for the MIC field.
    reservedSize = static_cast<uint16_t>(reservedSize + Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES);

    // ... and the overhead for end of AttributeDataIBs (end of container), more chunks flag, end of WriteRequestMessage (another
    // end of container).
    reservedSize = static_cast<uint16_t>(reservedSize + kReservedSizeForTLVEncodingOverhead);

#if CONFIG_BUILD_FOR_HOST_UNIT_TEST
    // ... and for unit tests.
    reservedSize = static_cast<uint16_t>(reservedSize + mReservedSize);
#endif

    mMessageWriter.Init(std::move(packet));

    ReturnErrorOnFailure(mMessageWriter.ReserveBuffer(reservedSize));

    ReturnErrorOnFailure(mWriteRequestBuilder.Init(&mMessageWriter));
    mWriteRequestBuilder.SuppressResponse(mSuppressResponse);
    mWriteRequestBuilder.TimedRequest(mTimedWriteTimeoutMs.HasValue());
    ReturnErrorOnFailure(mWriteRequestBuilder.GetError());
    mWriteRequestBuilder.CreateWriteRequests();
    ReturnErrorOnFailure(mWriteRequestBuilder.GetError());

    TLV::TLVWriter * writer = mWriteRequestBuilder.GetWriter();
    VerifyOrReturnError(writer != nullptr, CHIP_ERROR_INCORRECT_STATE);

    return CHIP_NO_ERROR;
}

CHIP_ERROR WriteClient::TryPutSinglePreencodedAttributeWritePayload(const ConcreteDataAttributePath & attributePath,
                                                                    const TLV::TLVReader & data)
{
    TLV::TLVReader dataToWrite;
    dataToWrite.Init(data);

    TLV::TLVWriter * writer = nullptr;

    ReturnErrorOnFailure(PrepareAttributeIB(attributePath));
    VerifyOrReturnError((writer = GetAttributeDataIBTLVWriter()) != nullptr, CHIP_ERROR_INCORRECT_STATE);
    ReturnErrorOnFailure(writer->CopyElement(TLV::ContextTag(to_underlying(AttributeDataIB::Tag::kData)), dataToWrite));
    ReturnErrorOnFailure(FinishAttributeIB());
    return CHIP_NO_ERROR;
}

CHIP_ERROR WriteClient::PutSinglePreencodedAttributeWritePayload(const chip::app::ConcreteDataAttributePath & attributePath,
                                                                 const TLV::TLVReader & data)
{
    TLV::TLVWriter backupWriter;

    mWriteRequestBuilder.GetWriteRequests().Checkpoint(backupWriter);

    // First attempt to write this attribute.
    CHIP_ERROR err = TryPutSinglePreencodedAttributeWritePayload(attributePath, data);
    if (err == CHIP_ERROR_NO_MEMORY || err == CHIP_ERROR_BUFFER_TOO_SMALL)
    {
        // If it failed with no memory, then we create a new chunk for it.
        mWriteRequestBuilder.GetWriteRequests().Rollback(backupWriter);
        mWriteRequestBuilder.GetWriteRequests().ResetError();
        ReturnErrorOnFailure(StartNewMessage());
        err = TryPutSinglePreencodedAttributeWritePayload(attributePath, data);
        // Since we have created a new chunk for this element, the encode is expected to succeed.
    }
    return err;
}

CHIP_ERROR WriteClient::PutPreencodedAttribute(const ConcreteDataAttributePath & attributePath, const TLV::TLVReader & data)
{
    ReturnErrorOnFailure(EnsureMessage());

    // ListIndex is missing and the data is an array -- we are writing a whole list.
    if (!attributePath.IsListOperation() && data.GetType() == TLV::TLVType::kTLVType_Array)
    {
        TLV::TLVReader dataReader;
        TLV::TLVReader valueReader;
        CHIP_ERROR err = CHIP_NO_ERROR;

        ConcreteDataAttributePath path = attributePath;

        dataReader.Init(data);
        dataReader.OpenContainer(valueReader);

        // Encode an empty list for the chunking protocol.
        ReturnErrorOnFailure(EncodeSingleAttributeDataIB(path, DataModel::List<uint8_t>()));

        if (err == CHIP_NO_ERROR)
        {
            path.mListOp = ConcreteDataAttributePath::ListOperation::AppendItem;
            while ((err = valueReader.Next()) == CHIP_NO_ERROR)
            {
                ReturnErrorOnFailure(PutSinglePreencodedAttributeWritePayload(path, valueReader));
            }
        }

        if (err == CHIP_END_OF_TLV)
        {
            err = CHIP_NO_ERROR;
        }
        return err;
    }
    // We are writing a non-list attribute, or we are writing a single element of a list.
    return PutSinglePreencodedAttributeWritePayload(attributePath, data);
}

const char * WriteClient::GetStateStr() const
{
#if CHIP_DETAIL_LOGGING
    switch (mState)
    {
    case State::Initialized:
        return "Initialized";

    case State::AddAttribute:
        return "AddAttribute";

    case State::AwaitingTimedStatus:
        return "AwaitingTimedStatus";

    case State::AwaitingResponse:
        return "AwaitingResponse";

    case State::ResponseReceived:
        return "ResponseReceived";

    case State::AwaitingDestruction:
        return "AwaitingDestruction";
    }
#endif // CHIP_DETAIL_LOGGING
    return "N/A";
}

void WriteClient::MoveToState(const State aTargetState)
{
    mState = aTargetState;
    ChipLogDetail(DataManagement, "WriteClient moving to [%10.10s]", GetStateStr());
}

CHIP_ERROR WriteClient::SendWriteRequest(const SessionHandle & session, System::Clock::Timeout timeout)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    VerifyOrExit(mState == State::AddAttribute, err = CHIP_ERROR_INCORRECT_STATE);

    err = FinalizeMessage(false /* hasMoreChunks */);
    SuccessOrExit(err);

    {
        // Create a new exchange context.
        auto exchange = mpExchangeMgr->NewContext(session, this);
        VerifyOrExit(exchange != nullptr, err = CHIP_ERROR_NO_MEMORY);

        mExchangeCtx.Grab(exchange);
    }

    VerifyOrReturnError(!(mExchangeCtx->IsGroupExchangeContext() && mHasDataVersion), CHIP_ERROR_INVALID_MESSAGE_TYPE);

    if (timeout == System::Clock::kZero)
    {
        mExchangeCtx->UseSuggestedResponseTimeout(app::kExpectedIMProcessingTime);
    }
    else
    {
        mExchangeCtx->SetResponseTimeout(timeout);
    }

    if (mTimedWriteTimeoutMs.HasValue())
    {
        err = TimedRequest::Send(mExchangeCtx.Get(), mTimedWriteTimeoutMs.Value());
        SuccessOrExit(err);
        MoveToState(State::AwaitingTimedStatus);
    }
    else
    {
        err = SendWriteRequest();
        SuccessOrExit(err);
    }

exit:
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DataManagement, "Write client failed to SendWriteRequest: %" CHIP_ERROR_FORMAT, err.Format());
    }
    else
    {
        // TODO: Ideally this would happen async, but to make sure that we
        // handle this object dying (e.g. due to IM enging shutdown) while the
        // async bits are pending we'd need to malloc some state bit that we can
        // twiddle if we die.  For now just do the OnDone callback sync.
        if (session->IsGroupSession())
        {
            // Always shutdown on Group communication
            ChipLogDetail(DataManagement, "Closing on group Communication ");

            // Tell the application to release the object.
            // TODO: Consumers expect to hand off ownership of the WriteClient and wait for OnDone
            // after SendWriteRequest returns success.  Calling OnDone before returning is weird.
            // Need to refactor the code to avoid this.
            Close();
        }
    }

    return err;
}

CHIP_ERROR WriteClient::SendWriteRequest()
{
    using namespace Protocols::InteractionModel;
    using namespace Messaging;

    System::PacketBufferHandle data = mChunks.PopHead();

    bool isGroupWrite = mExchangeCtx->IsGroupExchangeContext();
    if (!mChunks.IsNull() && isGroupWrite)
    {
        // Reject this request if we have more than one chunk (mChunks is not null after PopHead()), and this is a group
        // exchange context.
        return CHIP_ERROR_INCORRECT_STATE;
    }

    // kExpectResponse is ignored by ExchangeContext in case of groupcast
    ReturnErrorOnFailure(mExchangeCtx->SendMessage(MsgType::WriteRequest, std::move(data), SendMessageFlags::kExpectResponse));

    MoveToState(State::AwaitingResponse);
    return CHIP_NO_ERROR;
}

CHIP_ERROR WriteClient::OnMessageReceived(Messaging::ExchangeContext * apExchangeContext, const PayloadHeader & aPayloadHeader,
                                          System::PacketBufferHandle && aPayload)
{
    using namespace Protocols::InteractionModel;

    if (mState == State::AwaitingResponse &&
        // We had sent the last chunk of data, and received all responses
        mChunks.IsNull())
    {
        MoveToState(State::ResponseReceived);
    }

    CHIP_ERROR err          = CHIP_NO_ERROR;
    bool sendStatusResponse = false;
    // Assert that the exchange context matches the client's current context.
    // This should never fail because even if SendWriteRequest is called
    // back-to-back, the second call will call Close() on the first exchange,
    // which clears the OnMessageReceived callback.
    VerifyOrExit(apExchangeContext == mExchangeCtx.Get(), err = CHIP_ERROR_INCORRECT_STATE);

    sendStatusResponse = true;

    if (mState == State::AwaitingTimedStatus)
    {
        if (aPayloadHeader.HasMessageType(MsgType::StatusResponse))
        {
            CHIP_ERROR statusError = CHIP_NO_ERROR;
            SuccessOrExit(err = StatusResponse::ProcessStatusResponse(std::move(aPayload), statusError));
            sendStatusResponse = false;
            SuccessOrExit(err = statusError);
            err = SendWriteRequest();
        }
        else
        {
            err = CHIP_ERROR_INVALID_MESSAGE_TYPE;
        }
        // Skip all other processing here (which is for the response to the
        // write request), no matter whether err is success or not.
        goto exit;
    }

    if (aPayloadHeader.HasMessageType(MsgType::WriteResponse))
    {
        err = ProcessWriteResponseMessage(std::move(aPayload));
        SuccessOrExit(err);
        sendStatusResponse = false;
        if (!mChunks.IsNull())
        {
            // Send the next chunk.
            SuccessOrExit(SendWriteRequest());
        }
    }
    else if (aPayloadHeader.HasMessageType(MsgType::StatusResponse))
    {
        CHIP_ERROR statusError = CHIP_NO_ERROR;
        SuccessOrExit(err = StatusResponse::ProcessStatusResponse(std::move(aPayload), statusError));
        SuccessOrExit(err = statusError);
        err = CHIP_ERROR_INVALID_MESSAGE_TYPE;
    }
    else
    {
        err = CHIP_ERROR_INVALID_MESSAGE_TYPE;
    }

exit:
    if (mpCallback != nullptr)
    {
        if (err != CHIP_NO_ERROR)
        {
            mpCallback->OnError(this, err);
        }
    }

    if (sendStatusResponse)
    {
        StatusResponse::Send(Status::InvalidAction, apExchangeContext, false /*aExpectResponse*/);
    }

    if (mState != State::AwaitingResponse)
    {
        Close();
    }
    // Else we got a response to a Timed Request and just sent the write.

    return err;
}

void WriteClient::OnResponseTimeout(Messaging::ExchangeContext * apExchangeContext)
{
    ChipLogError(DataManagement, "Time out! failed to receive write response from Exchange: " ChipLogFormatExchange,
                 ChipLogValueExchange(apExchangeContext));

    if (mpCallback != nullptr)
    {
        mpCallback->OnError(this, CHIP_ERROR_TIMEOUT);
    }
    Close();
}

CHIP_ERROR WriteClient::ProcessAttributeStatusIB(AttributeStatusIB::Parser & aAttributeStatusIB)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    AttributePathIB::Parser attributePathParser;
    StatusIB statusIB;
    StatusIB::Parser StatusIBParser;
    ConcreteDataAttributePath attributePath;

    err = aAttributeStatusIB.GetPath(&attributePathParser);
    SuccessOrExit(err);

    err = attributePathParser.GetCluster(&(attributePath.mClusterId));
    SuccessOrExit(err);
    err = attributePathParser.GetEndpoint(&(attributePath.mEndpointId));
    SuccessOrExit(err);
    err = attributePathParser.GetAttribute(&(attributePath.mAttributeId));
    SuccessOrExit(err);
    err = attributePathParser.GetListIndex(attributePath);
    SuccessOrExit(err);

    err = aAttributeStatusIB.GetErrorStatus(&(StatusIBParser));
    if (CHIP_NO_ERROR == err)
    {
        err = StatusIBParser.DecodeStatusIB(statusIB);
        SuccessOrExit(err);
        if (mpCallback != nullptr)
        {
            mpCallback->OnResponse(this, attributePath, statusIB);
        }
    }

exit:
    return err;
}

} // namespace app
} // namespace chip
