/**
 *
 *    Copyright (c) 2021 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 "platform/android/CHIPP256KeypairBridge.h"
#include "lib/core/CHIPError.h"
#include "lib/support/CHIPJNIError.h"
#include "lib/support/JniReferences.h"
#include "lib/support/JniTypeWrappers.h"
#include "lib/support/SafeInt.h"

#include <array>
#include <cstdint>
#include <cstdlib>
#include <jni.h>
#include <platform/PlatformManager.h>
#include <string.h>
#include <type_traits>

using namespace chip;
using namespace chip::Crypto;

CHIPP256KeypairBridge::~CHIPP256KeypairBridge()
{
    VerifyOrReturn(mDelegate != nullptr);
    JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr);
    env->DeleteGlobalRef(mDelegate);
}

CHIP_ERROR CHIPP256KeypairBridge::SetDelegate(jobject delegate)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrExit(env != nullptr, err = CHIP_JNI_ERROR_NO_ENV);

    mDelegate = env->NewGlobalRef(delegate);

    err = JniReferences::GetInstance().GetClassRef(env, "chip/devicecontroller/KeypairDelegate", mKeypairDelegateClass);
    VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "Failed to find class for KeypairDelegate."));

    err = JniReferences::GetInstance().FindMethod(env, delegate, "createCertificateSigningRequest", "()[B",
                                                  &mCreateCertificateSigningRequestMethod);
    VerifyOrExit(err == CHIP_NO_ERROR,
                 ChipLogError(Controller, "Failed to find KeypairDelegate.createCertificateSigningRequest() method."));

    err = JniReferences::GetInstance().FindMethod(env, delegate, "getPublicKey", "()[B", &mGetPublicKeyMethod);
    VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "Failed to find KeypairDelegate.getPublicKey() method."));

    err = JniReferences::GetInstance().FindMethod(env, delegate, "ecdsaSignMessage", "([B)[B", &mEcdsaSignMessageMethod);
    VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "Failed to find KeypairDelegate.ecdsaSignMessage() method."));

exit:
    return err;
}

CHIP_ERROR CHIPP256KeypairBridge::Initialize(ECPKeyTarget key_target)
{
    if (HasKeypair())
    {
        SetPubkey();
    }
    return CHIP_NO_ERROR;
}

CHIP_ERROR CHIPP256KeypairBridge::Serialize(P256SerializedKeypair & output) const
{
    if (!HasKeypair())
    {
        return CHIP_ERROR_INCORRECT_STATE;
    }

    return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
}

CHIP_ERROR CHIPP256KeypairBridge::Deserialize(P256SerializedKeypair & input)
{
    if (!HasKeypair())
    {
        return CHIP_ERROR_INCORRECT_STATE;
    }

    return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
}

CHIP_ERROR CHIPP256KeypairBridge::NewCertificateSigningRequest(uint8_t * csr, size_t & csr_length) const
{
    if (!HasKeypair())
    {
        return CHIP_ERROR_INCORRECT_STATE;
    }

    // Not supported for use from within the CHIP SDK. We provide our own
    // implementation that is JVM-specific.
    return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
}

CHIP_ERROR CHIPP256KeypairBridge::ECDSA_sign_msg(const uint8_t * msg, size_t msg_length, P256ECDSASignature & out_signature) const
{
    if (!HasKeypair())
    {
        return CHIP_ERROR_INCORRECT_STATE;
    }

    VerifyOrReturnError(CanCastTo<uint32_t>(msg_length), CHIP_ERROR_INVALID_ARGUMENT);

    CHIP_ERROR err = CHIP_NO_ERROR;
    jbyteArray jniMsg;
    jobject signedResult = nullptr;
    JNIEnv * env         = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturnError(env != nullptr, err = CHIP_JNI_ERROR_NO_ENV);
    err = JniReferences::GetInstance().N2J_ByteArray(env, msg, static_cast<uint32_t>(msg_length), jniMsg);
    VerifyOrReturnError(err == CHIP_NO_ERROR, err);
    VerifyOrReturnError(jniMsg != nullptr, err);

    signedResult = env->CallObjectMethod(mDelegate, mEcdsaSignMessageMethod, jniMsg);

    if (env->ExceptionCheck())
    {
        ChipLogError(Controller, "Java exception in KeypairDelegate.ecdsaSignMessage()");
        env->ExceptionDescribe();
        env->ExceptionClear();
        return CHIP_JNI_ERROR_EXCEPTION_THROWN;
    }

    JniByteArray jniSignature(env, static_cast<jbyteArray>(signedResult));
    MutableByteSpan signatureSpan(out_signature.Bytes(), out_signature.Capacity());
    ReturnErrorOnFailure(EcdsaAsn1SignatureToRaw(CHIP_CRYPTO_GROUP_SIZE_BYTES, jniSignature.byteSpan(), signatureSpan));
    ReturnErrorOnFailure(out_signature.SetLength(signatureSpan.size()));

    return err;
}

CHIP_ERROR CHIPP256KeypairBridge::ECDH_derive_secret(const P256PublicKey & remote_public_key,
                                                     P256ECDHDerivedSecret & out_secret) const
{
    if (!HasKeypair())
    {
        return CHIP_ERROR_INCORRECT_STATE;
    }

    // Not required for Java SDK.
    return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
}

CHIP_ERROR CHIPP256KeypairBridge::SetPubkey()
{
    jobject publicKey = nullptr;
    JNIEnv * env      = nullptr;

    VerifyOrReturnError(HasKeypair(), CHIP_ERROR_INCORRECT_STATE);

    env = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturnError(env != nullptr, CHIP_JNI_ERROR_NO_ENV);

    publicKey = env->CallObjectMethod(mDelegate, mGetPublicKeyMethod);
    if (env->ExceptionCheck())
    {
        ChipLogError(Controller, "Java exception in KeypairDelegate.getPublicKey()");
        env->ExceptionDescribe();
        env->ExceptionClear();
        return CHIP_JNI_ERROR_EXCEPTION_THROWN;
    }

    VerifyOrReturnError(publicKey != nullptr, CHIP_JNI_ERROR_NULL_OBJECT);
    JniByteArray jniPublicKey(env, static_cast<jbyteArray>(publicKey));
    FixedByteSpan<Crypto::kP256_PublicKey_Length> publicKeySpan =
        FixedByteSpan<kP256_PublicKey_Length>(reinterpret_cast<const uint8_t *>(jniPublicKey.data()));
    mPublicKey = P256PublicKey(publicKeySpan);
    return CHIP_NO_ERROR;
}
