/*
 *
 *    Copyright (c) 2020 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 "TimedHandler.h"
#include <app/InteractionModelEngine.h>
#include <app/MessageDef/TimedRequestMessage.h>
#include <app/StatusResponse.h>
#include <lib/core/TLV.h>
#include <lib/support/logging/CHIPLogging.h>
#include <system/SystemClock.h>
#include <system/TLVPacketBufferBackingStore.h>

namespace chip {
namespace app {

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

    if (aExchangeContext->IsGroupExchangeContext())
    {
        // Timed interactions are always supposed to be unicast.  Nothing else
        // to do here; exchange will close and we'll free ourselves.
        ChipLogError(DataManagement, "Dropping Timed Request on group exchange " ChipLogFormatExchange,
                     ChipLogValueExchange(aExchangeContext));
        return CHIP_NO_ERROR;
    }

    if (mState == State::kExpectingTimedAction)
    {
        // We were just created; our caller should have done this only if it's
        // dealing with a Timed Request message.
        VerifyOrDie(aPayloadHeader.HasMessageType(MsgType::TimedRequest));
        mState         = State::kReceivedTimedAction;
        CHIP_ERROR err = HandleTimedRequestAction(aExchangeContext, aPayloadHeader, std::move(aPayload));
        if (err != CHIP_NO_ERROR)
        {
            ChipLogError(DataManagement, "Failed to parse Timed Request action: handler %p exchange " ChipLogFormatExchange, this,
                         ChipLogValueExchange(aExchangeContext));
            StatusResponse::Send(Status::InvalidAction, aExchangeContext, /* aExpectResponse = */ false);
        }
        return err;
    }

    if (mState == State::kExpectingFollowingAction)
    {
        System::Clock::Timestamp now = System::SystemClock().GetMonotonicTimestamp();
        ChipLogDetail(DataManagement,
                      "Timed following action arrived at 0x" ChipLogFormatX64 ": handler %p exchange " ChipLogFormatExchange,
                      ChipLogValueX64(now.count()), this, ChipLogValueExchange(aExchangeContext));
        if (now > mTimeLimit)
        {
            // Time is up.  Spec says to send UNSUPPORTED_ACCESS.
            ChipLogError(DataManagement, "Timeout expired: handler %p exchange " ChipLogFormatExchange, this,
                         ChipLogValueExchange(aExchangeContext));
            return StatusResponse::Send(Status::UnsupportedAccess, aExchangeContext, /* aExpectResponse = */ false);
        }

        if (aPayloadHeader.HasMessageType(MsgType::InvokeCommandRequest))
        {
            auto * imEngine = InteractionModelEngine::GetInstance();
            ChipLogDetail(DataManagement, "Handing timed invoke to IM engine: handler %p exchange " ChipLogFormatExchange, this,
                          ChipLogValueExchange(aExchangeContext));
            imEngine->OnTimedInvoke(this, aExchangeContext, aPayloadHeader, std::move(aPayload));
            return CHIP_NO_ERROR;
        }

        if (aPayloadHeader.HasMessageType(MsgType::WriteRequest))
        {
            auto * imEngine = InteractionModelEngine::GetInstance();
            ChipLogDetail(DataManagement, "Handing timed write to IM engine: handler %p exchange " ChipLogFormatExchange, this,
                          ChipLogValueExchange(aExchangeContext));
            imEngine->OnTimedWrite(this, aExchangeContext, aPayloadHeader, std::move(aPayload));
            return CHIP_NO_ERROR;
        }
    }

    // Not an expected message.  Send an error response.  The exchange will
    // close when we return.
    ChipLogError(DataManagement, "Unexpected unknown message in tiemd interaction: handler %p exchange " ChipLogFormatExchange,
                 this, ChipLogValueExchange(aExchangeContext));

    return StatusResponse::Send(Status::InvalidAction, aExchangeContext, /* aExpectResponse = */ false);
}

void TimedHandler::OnExchangeClosing(Messaging::ExchangeContext *)
{
    InteractionModelEngine::GetInstance()->OnTimedInteractionFailed(this);
}

CHIP_ERROR TimedHandler::HandleTimedRequestAction(Messaging::ExchangeContext * aExchangeContext,
                                                  const PayloadHeader & aPayloadHeader, System::PacketBufferHandle && aPayload)
{
    using namespace Protocols::InteractionModel;

    System::PacketBufferTLVReader reader;
    reader.Init(std::move(aPayload));
    TimedRequestMessage::Parser parser;
    ReturnErrorOnFailure(parser.Init(reader));

#if CHIP_CONFIG_IM_PRETTY_PRINT
    parser.PrettyPrint();
#endif

    uint16_t timeoutMs;
    ReturnErrorOnFailure(parser.GetTimeoutMs(&timeoutMs));
    ReturnErrorOnFailure(parser.ExitContainer());

    ChipLogDetail(DataManagement, "Got Timed Request with timeout %u: handler %p exchange " ChipLogFormatExchange, timeoutMs, this,
                  ChipLogValueExchange(aExchangeContext));
    // Use at least our default IM timeout, because if we close our exchange as
    // soon as we know the delay has passed we won't be able to send the
    // UNSUPPORTED_ACCESS status code the spec tells us to send (and in fact
    // will send nothing and the other side will have to time out to realize
    // it's missed its window).
    auto delay = System::Clock::Milliseconds32(timeoutMs);
    aExchangeContext->SetResponseTimeout(
        std::max(delay, aExchangeContext->GetSessionHandle()->ComputeRoundTripTimeout(app::kExpectedIMProcessingTime)));
    ReturnErrorOnFailure(StatusResponse::Send(Status::Success, aExchangeContext, /* aExpectResponse = */ true));

    // Now just wait for the client.
    mState     = State::kExpectingFollowingAction;
    mTimeLimit = System::SystemClock().GetMonotonicTimestamp() + delay;
    ChipLogDetail(DataManagement, "Timed Request time limit 0x" ChipLogFormatX64 ": handler %p exchange " ChipLogFormatExchange,
                  ChipLogValueX64(mTimeLimit.count()), this, ChipLogValueExchange(aExchangeContext));
    return CHIP_NO_ERROR;
}

} // namespace app
} // namespace chip
