/*
 *    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 <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>
#include <zap-generated/CHIPClusters.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(status = ManualSetupPayloadGenerator(payload).payloadDecimalStringRepresentation(manualPairingCode));
        SuccessOrExit(status = 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
