/*
 *
 *    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 <app/util/af.h>

#include <app-common/zap-generated/af-structs.h>
#include <app-common/zap-generated/attribute-id.h>
#include <app-common/zap-generated/attribute-type.h>
#include <app-common/zap-generated/command-id.h>
#include <app-common/zap-generated/ids/Clusters.h>

using namespace chip;
using namespace chip::app::Clusters;
#define MAX_LEVEL 99
#define MIN_LEVEL 1

typedef struct
{
    CommandId commandId;
    uint16_t storedLevel;
    bool increasing;
} EmberAfLevelControlState;

static EmberAfLevelControlState stateTable[EMBER_AF_LEVEL_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT];

static EmberAfLevelControlState * getState(EndpointId endpoint)
{
    uint8_t ep = emberAfFindClusterServerEndpointIndex(endpoint, LevelControl::Id);
    return (ep == 0xFF ? NULL : &stateTable[ep]);
}

static void stepHandler(CommandId commandId, uint8_t stepMode, uint8_t stepSize, pp::DataModel::Nullable<uint16_t> transitionTimeDs,
                        BitMask<LevelControl::LevelControlOptions> optionMask,
                        BitMask<LevelControl::LevelControlOptions> optionOverride)
{

    EndpointId endpoint              = emberAfCurrentEndpoint();
    EmberAfLevelControlState * state = getState(endpoint);
    EmberAfStatus status;
    app::DataModel::Nullable<uint8_t> nullableCurrentLevel;
    uint8_t currentLevel;

    status = Attributes::CurrentLevel::Get(endpoint, nullableCurrentLevel);
    if (status != EMBER_ZCL_STATUS_SUCCESS)
    {
        emberAfLevelControlClusterPrintln("ERR: reading current level %x", status);
        goto send_default_response;
    }

    if (nullableCurrentLevel.IsNull())
    {
        emberAfLevelControlClusterPrintln("ERR: Current Level is null");
        status = EMBER_ZCL_STATUS_FAILURE;

        goto send_default_response;
    }

    currentLevel = nullableCurrentLevel.Value();

    switch (stepMode)
    {
    case EMBER_ZCL_STEP_MODE_UP:
        state->increasing = true;
        if (MAX_LEVEL >= currentLevel + stepSize)
        {
            currentLevel = currentLevel + stepSize;
        }
        break;
    case EMBER_ZCL_STEP_MODE_DOWN:
        state->increasing = false;
        if (MIN_LEVEL <= currentLevel - stepSize)
        {
            currentLevel = currentLevel - stepSize;
        }
        break;
    default:
        status = EMBER_ZCL_STATUS_INVALID_FIELD;
        goto send_default_response;
    }

    if (currentLevel != state->storedLevel)
    {
        int volumeIncrementCount = abs(currentLevel - state->storedLevel);
        for (int i = 0; i < volumeIncrementCount; ++i)
        {
            if (state->increasing)
            {
                ChipLogProgress(Zcl, "Volume UP");
                // TODO: Insert your code here to send volume up command
            }
            else
            {
                ChipLogProgress(Zcl, "Volume DOWN");
                // TODO: Insert your code here to send volume down command
            }
        }

        nullableCurrentLevel.SetNonNull(currentLevel);
        status = Attributes::CurrentLevel::Set(endpoint, nullableCurrentLevel);

        state->storedLevel = currentLevel;
        ChipLogProgress(Zcl, "Setting volume to new level %d", state->storedLevel);
    }

send_default_response:
    if (emberAfCurrentCommand()->apsFrame->clusterId == LevelControl::Id)
    {
        emberAfSendImmediateDefaultResponse(status);
    }
}

bool emberAfLevelControlClusterStepCallback(uint8_t stepMode, uint8_t stepSize, pp::DataModel::Nullable<uint8_t> transitionTime,
                                            BitMask<LevelControl::LevelControlOptions> optionMask,
                                            BitMask<LevelControl::LevelControlOptions> optionOverride)
{
    stepHandler(ZCL_STEP_COMMAND_ID, stepMode, stepSize, transitionTime, optionMask, optionOverride);
    return true;
}

bool emberAfLevelControlClusterMoveCallback(unsigned char, unsigned char, unsigned char, unsigned char)
{
    ChipLogProgress(Zcl, "Not supported");
    return true;
}

bool emberAfLevelControlClusterMoveToLevelCallback(unsigned char, unsigned short, unsigned char, unsigned char)
{
    ChipLogProgress(Zcl, "Not supported");
    return true;
}

bool emberAfLevelControlClusterMoveToLevelWithOnOffCallback(unsigned char, unsigned short)
{
    ChipLogProgress(Zcl, "Not supported");
    return true;
}

bool emberAfLevelControlClusterMoveWithOnOffCallback(unsigned char, unsigned char)
{
    ChipLogProgress(Zcl, "Not supported");
    return true;
}

bool emberAfLevelControlClusterStopCallback(unsigned char, unsigned char)
{
    ChipLogProgress(Zcl, "Not supported");
    return true;
}

bool emberAfLevelControlClusterStopWithOnOffCallback()
{
    ChipLogProgress(Zcl, "Not supported");
    return true;
}

bool emberAfOnOffClusterLevelControlEffectCallback(unsigned char, bool)
{
    ChipLogProgress(Zcl, "Not supported");
    return true;
}

bool emberAfLevelControlClusterServerInitCallback(unsigned char)
{
    ChipLogProgress(Zcl, "Not supported");
    return true;
}

bool emberAfLevelControlClusterStepWithOnOffCallback(unsigned char, unsigned char, unsigned short)
{
    ChipLogProgress(Zcl, "Not supported");
    return true;
}

bool emberAfLevelControlClusterServerTickCallback(unsigned char)
{
    ChipLogProgress(Zcl, "Not supported");
    return true;
}
