/**
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *
 *    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 "barrier-control-server.h"
#include <app-common/zap-generated/af-structs.h>
#include <app-common/zap-generated/attributes/Accessors.h>
#include <app-common/zap-generated/cluster-objects.h>
#include <app-common/zap-generated/ids/Clusters.h>
#include <app/CommandHandler.h>
#include <app/ConcreteCommandPath.h>
#include <app/util/af.h>

#include <assert.h>

// We need this for initializating default reporting configurations.
#include <app/reporting/reporting.h>

using namespace chip;
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::BarrierControl;

typedef struct
{
    uint8_t currentPosition;
    uint8_t targetPosition;
    bool increasing;
    uint32_t delayMs;
} State;
static State state;

#ifdef EMBER_SCRIPTED_TEST
#define ZCL_USING_BARRIER_CONTROL_CLUSTER_OPEN_PERIOD_ATTRIBUTE
#define ZCL_USING_BARRIER_CONTROL_CLUSTER_CLOSE_PERIOD_ATTRIBUTE
#define ZCL_USING_BARRIER_CONTROL_CLUSTER_BARRIER_OPEN_EVENTS_ATTRIBUTE
#define ZCL_USING_BARRIER_CONTROL_CLUSTER_BARRIER_CLOSE_EVENTS_ATTRIBUTE
#define ZCL_USING_BARRIER_CONTROL_CLUSTER_BARRIER_COMMAND_OPEN_EVENTS_ATTRIBUTE
#define ZCL_USING_BARRIER_CONTROL_CLUSTER_BARRIER_COMMAND_CLOSE_EVENTS_ATTRIBUTE
#endif

// -----------------------------------------------------------------------------
// Accessing attributes

uint8_t emAfPluginBarrierControlServerGetBarrierPosition(EndpointId endpoint)
{
    uint8_t position;
    EmberAfStatus status = Attributes::BarrierPosition::Get(endpoint, &position);
    assert(status == EMBER_ZCL_STATUS_SUCCESS);
    return position;
}

void emAfPluginBarrierControlServerSetBarrierPosition(EndpointId endpoint, uint8_t position)
{
    EmberAfStatus status = Attributes::BarrierPosition::Set(endpoint, position);
    assert(status == EMBER_ZCL_STATUS_SUCCESS);
}

bool emAfPluginBarrierControlServerIsPartialBarrierSupported(EndpointId endpoint)
{
    uint8_t bitmap;
    EmberAfStatus status = Attributes::BarrierCapabilities::Get(endpoint, &bitmap);
    assert(status == EMBER_ZCL_STATUS_SUCCESS);
    return READBITS(bitmap, EMBER_AF_BARRIER_CONTROL_CAPABILITIES_PARTIAL_BARRIER);
}

static uint16_t getOpenOrClosePeriod(EndpointId endpoint, bool open)
{
    uint16_t period      = 0;
    EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS;
#if defined(ZCL_USING_BARRIER_CONTROL_CLUSTER_BARRIER_OPEN_PERIOD_ATTRIBUTE)
    if (open)
    {
        status = Attributes::BarrierOpenPeriod::Get(endpoint, &period);
    }
#endif
#if defined(ZCL_USING_BARRIER_CONTROL_CLUSTER_BARRIER_CLOSE_PERIOD_ATTRIBUTE)
    if (!open)
    {
        status = Attributes::BarrierClosePeriod::Get(endpoint, &period);
    }
#endif
    assert(status == EMBER_ZCL_STATUS_SUCCESS);
    return period;
}

static void setMovingState(EndpointId endpoint, uint8_t newState)
{
    EmberAfStatus status = Attributes::BarrierMovingState::Set(endpoint, newState);
    assert(status == EMBER_ZCL_STATUS_SUCCESS);
}

uint16_t emAfPluginBarrierControlServerGetSafetyStatus(EndpointId endpoint)
{
    uint16_t safetyStatus;
    EmberAfStatus status = Attributes::BarrierSafetyStatus::Get(endpoint, &safetyStatus);
    assert(status == EMBER_ZCL_STATUS_SUCCESS);
    return safetyStatus;
}

static bool isRemoteLockoutOn(EndpointId endpoint)
{
    uint16_t safetyStatus = emAfPluginBarrierControlServerGetSafetyStatus(endpoint);
    return READBITS(safetyStatus, EMBER_AF_BARRIER_CONTROL_SAFETY_STATUS_REMOTE_LOCKOUT);
}

void emAfPluginBarrierControlServerIncrementEvents(EndpointId endpoint, bool open, bool command)
{
    EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS;
    uint16_t events      = 0;

#if defined(ZCL_USING_BARRIER_CONTROL_CLUSTER_BARRIER_OPEN_EVENTS_ATTRIBUTE)
    if (open && !command)
    {
        status = Attributes::BarrierOpenEvents::Get(endpoint, &events);
    }
#endif
#if defined(ZCL_USING_BARRIER_CONTROL_CLUSTER_BARRIER_CLOSE_EVENTS_ATTRIBUTE)
    if (!open && !command)
    {
        status = Attributes::BarrierCloseEvents::Get(endpoint, &events);
    }
#endif
#if defined(ZCL_USING_BARRIER_CONTROL_CLUSTER_BARRIER_COMMAND_OPEN_EVENTS_ATTRIBUTE)
    if (open && command)
    {
        status = Attributes::BarrierCommandOpenEvents::Get(endpoint, &events);
    }
#endif
#if defined(ZCL_USING_BARRIER_CONTROL_CLUSTER_BARRIER_COMMAND_CLOSE_EVENTS_ATTRIBUTE)
    if (!open && command)
    {
        status = Attributes::BarrierCommandCloseEvents::Get(endpoint, &events);
    }
#endif
    assert(status == EMBER_ZCL_STATUS_SUCCESS);

    // Section 7.1.2.1.5-8 says that this events counter SHALL NOT roll over.
    // The maximum 16-bit unsigned integer in Zigbee is 0xFFFE, so we have this
    // check here.
    if (events == UINT16_MAX - 1)
    {
        return;
    }
    events++;

#if defined(ZCL_USING_BARRIER_CONTROL_CLUSTER_BARRIER_OPEN_EVENTS_ATTRIBUTE)
    if (open && !command)
    {
        status = Attributes::BarrierOpenEvents::Set(endpoint, events);
    }
#endif
#if defined(ZCL_USING_BARRIER_CONTROL_CLUSTER_BARRIER_CLOSE_EVENTS_ATTRIBUTE)
    if (!open && !command)
    {
        status = Attributes::BarrierCloseEvents::Set(endpoint, events);
    }
#endif
#if defined(ZCL_USING_BARRIER_CONTROL_CLUSTER_BARRIER_COMMAND_OPEN_EVENTS_ATTRIBUTE)
    if (open && command)
    {
        status = Attributes::BarrierCommandOpenEvents::Set(endpoint, events);
    }
#endif
#if defined(ZCL_USING_BARRIER_CONTROL_CLUSTER_BARRIER_COMMAND_CLOSE_EVENTS_ATTRIBUTE)
    if (!open && command)
    {
        status = Attributes::BarrierCommandCloseEvents::Set(endpoint, events);
    }
#endif
    assert(status == EMBER_ZCL_STATUS_SUCCESS);
}

// -----------------------------------------------------------------------------
// Opening/closing barrier

static uint8_t getCurrentPosition(EndpointId endpoint)
{
    // If the BarrierPosition attribute does not store the exact position of the
    // barrier, then it will be set to 0xFF. If this is the case, then we have no
    // way of knowing the position of the barrier. Let's guess that the barrier is
    // open so that we don't leave the barrier open when it should be closed.
    uint8_t currentPositionFromAttribute = emAfPluginBarrierControlServerGetBarrierPosition(endpoint);
    return ((currentPositionFromAttribute == EMBER_ZCL_BARRIER_CONTROL_BARRIER_POSITION_UNKNOWN)
                ? static_cast<uint8_t>(EMBER_ZCL_BARRIER_CONTROL_BARRIER_POSITION_OPEN)
                : currentPositionFromAttribute);
}

static uint32_t calculateDelayMs(EndpointId endpoint, uint8_t targetPosition, bool * opening)
{
    uint8_t currentPosition = emAfPluginBarrierControlServerGetBarrierPosition(endpoint);
    *opening                = targetPosition > currentPosition;
    uint8_t positionDelta   = static_cast<uint8_t>(*opening ? targetPosition - currentPosition : currentPosition - targetPosition);
    uint16_t openOrClosePeriodDs = getOpenOrClosePeriod(endpoint, *opening);
    uint32_t openOrClosePeriodMs = openOrClosePeriodDs * MILLISECOND_TICKS_PER_DECISECOND;

    // We use a minimum delay so that our barrier changes position in a realistic
    // amount of time.
    if (openOrClosePeriodDs == 0 || positionDelta == 0)
    {
        return MIN_POSITION_CHANGE_DELAY_MS;
    }

    uint32_t delayMs = openOrClosePeriodMs / positionDelta;
    return (delayMs < MIN_POSITION_CHANGE_DELAY_MS ? MIN_POSITION_CHANGE_DELAY_MS : delayMs);
}

void emberAfBarrierControlClusterServerTickCallback(EndpointId endpoint)
{
    if (state.currentPosition == state.targetPosition)
    {
        emAfPluginBarrierControlServerSetBarrierPosition(endpoint, state.currentPosition);
        setMovingState(endpoint, EMBER_ZCL_BARRIER_CONTROL_MOVING_STATE_STOPPED);
        emberAfDeactivateServerTick(endpoint, BarrierControl::Id);
    }
    else
    {
        if (state.increasing)
        {
            if (++state.currentPosition == 1)
            {
                // Zero -> nonzero: open event
                emAfPluginBarrierControlServerIncrementEvents(endpoint, true, false);
            }
        }
        else
        {
            if (--state.currentPosition == 0)
            {
                // Nonzero -> zero: close event
                emAfPluginBarrierControlServerIncrementEvents(endpoint, false, false);
            }
        }
        emAfPluginBarrierControlServerSetBarrierPosition(
            endpoint,
            (emAfPluginBarrierControlServerIsPartialBarrierSupported(endpoint)
                 ? state.currentPosition
                 : static_cast<uint8_t>(EMBER_ZCL_BARRIER_CONTROL_BARRIER_POSITION_UNKNOWN)));
        setMovingState(
            endpoint,
            (state.increasing ? EMBER_ZCL_BARRIER_CONTROL_MOVING_STATE_OPENING : EMBER_ZCL_BARRIER_CONTROL_MOVING_STATE_CLOSING));
        emberAfScheduleServerTick(endpoint, BarrierControl::Id, state.delayMs);
    }
}

// -----------------------------------------------------------------------------
// Handling commands

static void sendDefaultResponse(EmberAfStatus status)
{
    if (emberAfSendImmediateDefaultResponse(status) != EMBER_SUCCESS)
    {
        emberAfBarrierControlClusterPrintln("Failed to send default response");
    }
}

bool emberAfBarrierControlClusterBarrierControlGoToPercentCallback(
    app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
    const Commands::BarrierControlGoToPercent::DecodableType & commandData)
{
    auto & percentOpen = commandData.percentOpen;

    EndpointId endpoint  = commandPath.mEndpointId;
    EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS;

    emberAfBarrierControlClusterPrintln("RX: GoToPercentCallback p=%d", percentOpen);

    if (isRemoteLockoutOn(endpoint))
    {
        status = EMBER_ZCL_STATUS_FAILURE;
    }
    else if (percentOpen > 100 // "100" means "100%", so greater than that is invalid
             || (!emAfPluginBarrierControlServerIsPartialBarrierSupported(endpoint) &&
                 percentOpen != EMBER_ZCL_BARRIER_CONTROL_BARRIER_POSITION_CLOSED &&
                 percentOpen != EMBER_ZCL_BARRIER_CONTROL_BARRIER_POSITION_OPEN))
    {
        status = EMBER_ZCL_STATUS_INVALID_VALUE;
    }
    else
    {
        state.currentPosition = getCurrentPosition(endpoint);
        state.targetPosition  = percentOpen;
        state.delayMs         = calculateDelayMs(endpoint, state.targetPosition, &state.increasing);
        emberAfBarrierControlClusterPrintln("Scheduling barrier move from %d to %d with %" PRIu32 "ms delay", state.currentPosition,
                                            state.targetPosition, state.delayMs);
        emberAfScheduleServerTick(endpoint, BarrierControl::Id, state.delayMs);

        if (state.currentPosition < state.targetPosition)
        {
            emAfPluginBarrierControlServerIncrementEvents(endpoint, true, true);
        }
        else if (state.currentPosition > state.targetPosition)
        {
            emAfPluginBarrierControlServerIncrementEvents(endpoint, false, true);
        }
    }

    sendDefaultResponse(status);

    return true;
}

bool emberAfBarrierControlClusterBarrierControlStopCallback(app::CommandHandler * commandObj,
                                                            const app::ConcreteCommandPath & commandPath,
                                                            const Commands::BarrierControlStop::DecodableType & commandData)
{
    EndpointId endpoint = commandPath.mEndpointId;
    emberAfDeactivateServerTick(endpoint, BarrierControl::Id);
    setMovingState(endpoint, EMBER_ZCL_BARRIER_CONTROL_MOVING_STATE_STOPPED);
    sendDefaultResponse(EMBER_ZCL_STATUS_SUCCESS);
    return true;
}

void MatterBarrierControlPluginServerInitCallback() {}
