/*
 *
 *    Copyright (c) 2021 Project CHIP Authors
 *    Copyright (c) 2019 Google LLC.
 *    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 "LightingManager.h"
#include <app-common/zap-generated/att-storage.h>
#include <app-common/zap-generated/attribute-id.h>
#include <app-common/zap-generated/attribute-type.h>
#include <app-common/zap-generated/attributes/Accessors.h>
#include <app/util/af.h>
#include <stdio.h>

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

LightingManager LightingManager::sLight;

CHIP_ERROR LightingManager::Init()
{
    mState = kState_OffCompleted;

    return CHIP_NO_ERROR;
}

void LightingManager::SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB)
{
    mActionInitiated_CB = aActionInitiated_CB;
    mActionCompleted_CB = aActionCompleted_CB;
}

bool LightingManager::IsActionInProgress()
{
    return (mState == kState_OffInitiated || mState == kState_OnInitiated);
}

bool LightingManager::IsLightOn(void)
{
    bool on                    = true;
    const EmberAfStatus status = OnOff::Attributes::OnOff::Get(1, &on);

    if (status != EMBER_ZCL_STATUS_SUCCESS)
    {
        printf("Error ReadServerAttribute 0x%02x\n", status);
    }

    return on != false;
}

bool LightingManager::InitiateAction(Actor_t aActor, Action_t aAction, uint8_t value)
{
    if (mActionInitiated_CB)
    {
        mActionInitiated_CB(aActor, aAction, value);
    }

    switch (aAction)
    {
    case ON_ACTION:
        mState = kState_OnInitiated;
        if (aActor != ACTOR_ZCL_CMD)
        {
            WriteClusterState(1);
        }
        mState = kState_OnCompleted;
        break;
    case OFF_ACTION:
        mState = kState_OffInitiated;
        if (aActor != ACTOR_ZCL_CMD)
        {
            WriteClusterState(0);
        }
        mState = kState_OffCompleted;
        break;
    default:
        return false;
    }

    if (mActionCompleted_CB)
    {
        mActionCompleted_CB(aAction);
    }

    return true;
}

void LightingManager::WriteClusterState(uint8_t value)
{
    const EmberAfStatus status = OnOff::Attributes::OnOff::Set(1, value);

    if (status != EMBER_ZCL_STATUS_SUCCESS)
    {
        printf("Error WriteServerAttribute 0x%02x\n", status);
    }
}

void LightingManager::WriteClusterLevel(uint8_t value)
{
    const EmberAfStatus status = LevelControl::Attributes::CurrentLevel::Set(1, value);

    if (status != EMBER_ZCL_STATUS_SUCCESS)
    {
        printf("Error WriteServerAttribute 0x%02x\n", status);
    }
}
