/*
 *    Copyright (c) 2022 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 "AndroidCommissioningWindowOpener.h"

#include <app-common/zap-generated/cluster-objects.h>
#include <controller-clusters/zap-generated/CHIPClusters.h>
#include <lib/core/CHIPSafeCasts.h>
#include <lib/support/CHIPMem.h>
#include <lib/support/JniReferences.h>
#include <lib/support/JniTypeWrappers.h>
#include <protocols/secure_channel/PASESession.h>
#include <setup_payload/ManualSetupPayloadGenerator.h>
#include <setup_payload/QRCodeSetupPayloadGenerator.h>

using namespace chip::app::Clusters;
using namespace chip::System::Clock;

namespace chip {
namespace Controller {

AndroidCommissioningWindowOpener::AndroidCommissioningWindowOpener(DeviceController * controller, jobject jCallbackObject) :
    CommissioningWindowOpener(controller), mOnOpenCommissioningWindowCallback(OnOpenCommissioningWindowResponse, this),
    mOnOpenBasicCommissioningWindowCallback(OnOpenBasicCommissioningWindowResponse, this)
{
    JNIEnv * env  = JniReferences::GetInstance().GetEnvForCurrentThread();
    mJavaCallback = env->NewGlobalRef(jCallbackObject);

    jclass callbackClass = env->GetObjectClass(jCallbackObject);

    mOnSuccessMethod = env->GetMethodID(callbackClass, "onSuccess", "(JLjava/lang/String;Ljava/lang/String;)V");
    if (mOnSuccessMethod == nullptr)
    {
        ChipLogError(Controller, "Failed to access callback 'onSuccess' method");
        env->ExceptionClear();
    }

    mOnErrorMethod = env->GetMethodID(callbackClass, "onError", "(IJ)V");
    if (mOnErrorMethod == nullptr)
    {
        ChipLogError(Controller, "Failed to access callback 'onError' method");
        env->ExceptionClear();
    }
}

AndroidCommissioningWindowOpener::~AndroidCommissioningWindowOpener()
{
    ChipLogError(Controller, "Delete AndroidCommissioningWindowOpener");
    JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
    env->DeleteGlobalRef(mJavaCallback);
}

CHIP_ERROR AndroidCommissioningWindowOpener::OpenBasicCommissioningWindow(DeviceController * controller, NodeId deviceId,
                                                                          Seconds16 timeout, jobject jcallback)
{
    // Not using Platform::New because we want to keep our constructor private.
    auto * opener = new AndroidCommissioningWindowOpener(controller, jcallback);
    if (opener == nullptr)
    {
        return CHIP_ERROR_NO_MEMORY;
    }

    CHIP_ERROR err = opener->CommissioningWindowOpener::OpenBasicCommissioningWindow(
        deviceId, timeout, &opener->mOnOpenBasicCommissioningWindowCallback);
    if (err != CHIP_NO_ERROR)
    {
        delete opener;
    }
    // Else will clean up when the callback is called.
    return err;
}

CHIP_ERROR AndroidCommissioningWindowOpener::OpenCommissioningWindow(DeviceController * controller, NodeId deviceId,
                                                                     Seconds16 timeout, uint32_t iteration, uint16_t discriminator,
                                                                     Optional<uint32_t> setupPIN, Optional<ByteSpan> salt,
                                                                     jobject jcallback, SetupPayload & payload,
                                                                     bool readVIDPIDAttributes)
{
    // Not using Platform::New because we want to keep our constructor private.
    auto * opener = new AndroidCommissioningWindowOpener(controller, jcallback);
    if (opener == nullptr)
    {
        return CHIP_ERROR_NO_MEMORY;
    }

    CHIP_ERROR err = opener->CommissioningWindowOpener::OpenCommissioningWindow(
        deviceId, timeout, iteration, discriminator, setupPIN, salt, &opener->mOnOpenCommissioningWindowCallback, payload,
        readVIDPIDAttributes);
    if (err != CHIP_NO_ERROR)
    {
        delete opener;
    }
    // Else will clean up when the callback is called.
    return err;
}

void AndroidCommissioningWindowOpener::OnOpenCommissioningWindowResponse(void * context, NodeId deviceId, CHIP_ERROR status,
                                                                         chip::SetupPayload payload)
{
    auto * self  = static_cast<AndroidCommissioningWindowOpener *>(context);
    JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();

    VerifyOrExit(self->mJavaCallback != nullptr, ChipLogError(Controller, "mJavaCallback is not allocated."));

    if (status == CHIP_NO_ERROR)
    {
        std::string QRCode;
        std::string manualPairingCode;

        SuccessOrExit(ManualSetupPayloadGenerator(payload).payloadDecimalStringRepresentation(manualPairingCode));
        SuccessOrExit(QRCodeSetupPayloadGenerator(payload).payloadBase38Representation(QRCode));

        if (self->mOnSuccessMethod != nullptr)
        {
            UtfString jManualPairingCode(env, manualPairingCode.c_str());
            UtfString jQRCode(env, QRCode.c_str());
            env->CallVoidMethod(self->mJavaCallback, self->mOnSuccessMethod, static_cast<jlong>(deviceId),
                                jManualPairingCode.jniValue(), jQRCode.jniValue());
        }
    }
    else
    {
        if (self->mOnErrorMethod != nullptr)
        {
            env->CallVoidMethod(self->mJavaCallback, self->mOnErrorMethod, static_cast<jint>(status.GetValue()),
                                static_cast<jlong>(deviceId));
        }
    }
exit:
    delete self;
}

void AndroidCommissioningWindowOpener::OnOpenBasicCommissioningWindowResponse(void * context, NodeId deviceId, CHIP_ERROR status)
{
    auto * self = static_cast<AndroidCommissioningWindowOpener *>(context);

    if (self->mJavaCallback != nullptr)
    {
        JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
        if (status == CHIP_NO_ERROR)
        {
            if (self->mOnSuccessMethod != nullptr)
            {
                UtfString jManualPairingCode(env, "");
                UtfString jQRCode(env, "");
                env->CallVoidMethod(self->mJavaCallback, self->mOnSuccessMethod, static_cast<jlong>(deviceId),
                                    jManualPairingCode.jniValue(), jQRCode.jniValue());
            }
        }
        else
        {
            if (self->mOnErrorMethod != nullptr)
            {
                env->CallVoidMethod(self->mJavaCallback, self->mOnErrorMethod, static_cast<jint>(status.GetValue()),
                                    static_cast<jlong>(deviceId));
            }
        }
    }

    delete self;
}

} // namespace Controller
} // namespace chip
