/**
 *
 *    Copyright (c) 2022 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 "LevelManager.h"
#include "TvApp-JNI.h"
#include <app-common/zap-generated/attributes/Accessors.h>
#include <app-common/zap-generated/ids/Clusters.h>
#include <app/util/attribute-storage.h>
#include <app/util/config.h>
#include <jni.h>
#include <lib/support/CHIPJNIError.h>
#include <lib/support/JniReferences.h>
#include <lib/support/JniTypeWrappers.h>

using namespace chip;

static constexpr size_t kLevelManagerTableSize = MATTER_DM_LEVEL_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT;

namespace {

LevelManager * gLevelManagerTable[kLevelManagerTableSize] = { nullptr };
static_assert(kLevelManagerTableSize <= kEmberInvalidEndpointIndex, "gLevelManagerTable table size error");

} // namespace

void emberAfLevelControlClusterInitCallback(EndpointId endpoint)
{
    ChipLogProgress(Zcl, "TV Android App::Level::PostClusterInit");
    TvAppJNIMgr().PostClusterInit(chip::app::Clusters::LevelControl::Id, endpoint);
}

void LevelManager::NewManager(jint endpoint, jobject manager)
{
    ChipLogProgress(Zcl, "TV Android App: LevelManager::NewManager");
    uint16_t ep = emberAfGetClusterServerEndpointIndex(static_cast<chip::EndpointId>(endpoint), app::Clusters::LevelControl::Id,
                                                       MATTER_DM_LEVEL_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT);
    VerifyOrReturn(ep < kLevelManagerTableSize,
                   ChipLogError(Zcl, "TV Android App::Level::NewManager: endpoint %d not found", endpoint));

    VerifyOrReturn(gLevelManagerTable[ep] == nullptr,
                   ChipLogError(Zcl, "TV Android App::Level::NewManager: endpoint %d already has a manager", endpoint));
    LevelManager * mgr = new LevelManager();
    CHIP_ERROR err     = mgr->InitializeWithObjects(manager);
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(Zcl, "TV Android App::Level::NewManager: failed to initialize manager for endpoint %d", endpoint);
        delete mgr;
    }
    else
    {
        gLevelManagerTable[ep] = mgr;
    }
}

LevelManager * GetLevelManager(EndpointId endpoint)
{
    uint16_t ep = emberAfGetClusterServerEndpointIndex(endpoint, app::Clusters::LevelControl::Id,
                                                       MATTER_DM_LEVEL_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT);
    return ((ep >= kLevelManagerTableSize) ? nullptr : gLevelManagerTable[ep]);
}

void LevelManager::PostLevelChanged(chip::EndpointId endpoint, uint8_t value)
{
    ChipLogProgress(Zcl, "TV Android App: LevelManager::PostLevelChanged");
    LevelManager * mgr = GetLevelManager(endpoint);
    VerifyOrReturn(mgr != nullptr, ChipLogError(Zcl, "LevelManager null"));

    mgr->HandleLevelChanged(value);
}

jboolean LevelManager::SetLevel(jint endpoint, jint value)
{
    chip::DeviceLayer::StackLock stack;
    chip::Protocols::InteractionModel::Status status = app::Clusters::LevelControl::Attributes::CurrentLevel::Set(
        static_cast<chip::EndpointId>(endpoint), static_cast<uint8_t>(value));
    return status == chip::Protocols::InteractionModel::Status::Success;
}

CHIP_ERROR LevelManager::InitializeWithObjects(jobject managerObject)
{
    JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturnLogError(env != nullptr, CHIP_ERROR_INCORRECT_STATE);
    JniLocalReferenceScope scope(env);

    ReturnLogErrorOnFailure(mLevelManagerObject.Init(managerObject));

    jclass LevelManagerClass = env->GetObjectClass(managerObject);
    VerifyOrReturnLogError(LevelManagerClass != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

    mHandleLevelChangedMethod = env->GetMethodID(LevelManagerClass, "HandleLevelChanged", "(I)V");
    if (mHandleLevelChangedMethod == nullptr)
    {
        ChipLogError(Zcl, "Failed to access LevelManager 'HandleLevelChanged' method");
        env->ExceptionClear();
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    return CHIP_NO_ERROR;
}

void LevelManager::HandleLevelChanged(uint8_t value)
{
    DeviceLayer::StackUnlock unlock;
    ChipLogProgress(Zcl, "LevelManager::HandleLevelChanged");

    JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNIEnv for current thread"));
    JniLocalReferenceScope scope(env);

    VerifyOrReturn(mLevelManagerObject.HasValidObjectRef(), ChipLogError(Zcl, "mLevelManagerObject is not valid"));
    VerifyOrReturn(mHandleLevelChangedMethod != nullptr, ChipLogProgress(Zcl, "mHandleLevelChangedMethod null"));

    env->ExceptionClear();
    env->CallVoidMethod(mLevelManagerObject.ObjectRef(), mHandleLevelChangedMethod, static_cast<jint>(value));
    if (env->ExceptionCheck())
    {
        ChipLogError(AppServer, "Java exception in LevelManager::HandleLevelChanged");
        env->ExceptionDescribe();
        env->ExceptionClear();
    }
}
