/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * 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 <stdlib.h>

#include "jni.h"
#include "JNIHelp.h"

#include "android_nfc.h"

namespace android {

static jint android_nfc_NdefMessage_parseNdefMessage(JNIEnv *e, jobject o,
        jbyteArray array)
{
    uint16_t status;
    uint32_t i;
    jbyte *raw_msg;
    jsize raw_msg_size;
    uint32_t num_of_records = 0;
    uint8_t **records = NULL;
    uint8_t *is_chunked = NULL;
    jint ret = -1;
    phFriNfc_NdefRecord_t record;

    jclass record_cls;
    jobjectArray records_array;
    jmethodID ctor;

    jclass msg_cls;
    jfieldID mrecords;

    raw_msg_size = e->GetArrayLength(array);
    raw_msg = e->GetByteArrayElements(array, NULL);
    if (raw_msg == NULL)
        return -1;

    /* Get the number of records in the message so we can allocate buffers */
    TRACE("phFriNfc_NdefRecord_GetRecords(NULL)");

    status = phFriNfc_NdefRecord_GetRecords((uint8_t *)raw_msg,
            (uint32_t)raw_msg_size, NULL, NULL, &num_of_records);

    if (status) {
        LOGE("phFriNfc_NdefRecord_GetRecords(NULL) returned 0x%04x", status);
        goto end;
    }
    TRACE("phFriNfc_NdefRecord_GetRecords(NULL) returned 0x%04x, with %d records", status, num_of_records);

    is_chunked = (uint8_t*)malloc(num_of_records);
    if (is_chunked == NULL)
        goto end;
    records = (uint8_t**)malloc(num_of_records * sizeof(uint8_t *));
    if (records == NULL)
        goto end;

    /* Now, actually retrieve records position in message */
    TRACE("phFriNfc_NdefRecord_GetRecords()");

    status = phFriNfc_NdefRecord_GetRecords((uint8_t *)raw_msg,
            (uint32_t)raw_msg_size, records, is_chunked, &num_of_records);

    if (status) {
        LOGE("phFriNfc_NdefRecord_GetRecords() returned 0x%04x", status);
        goto end;
    }
    TRACE("phFriNfc_NdefRecord_GetRecords() returned 0x%04x, with %d records", status, num_of_records);

    /* Build NDEF records array */
    record_cls = e->FindClass("android/nfc/NdefRecord");
    records_array = e->NewObjectArray((jsize)num_of_records, record_cls,
            NULL);
    if (records_array == NULL)
        goto end;

    ctor = e->GetMethodID(record_cls, "<init>", "(S[B[B[B)V");

    for (i = 0; i < num_of_records; i++) {
        jbyteArray type, id, payload;
        jobject new_record;

        TRACE("phFriNfc_NdefRecord_Parse()");

        status = phFriNfc_NdefRecord_Parse(&record, records[i]);

        if (status) {
            LOGE("phFriNfc_NdefRecord_Parse() returned 0x%04x", status);
            goto end;
        }
        TRACE("phFriNfc_NdefRecord_Parse() returned 0x%04x", status);

        type = e->NewByteArray(record.TypeLength);
        if (type == NULL) {
            LOGD("NFC_Set Record Type Error\n");
            goto end;
        }

        id = e->NewByteArray(record.IdLength);
        if(id == NULL) {
            LOGD("NFC_Set Record ID Error\n");
            goto end;
        }

        payload = e->NewByteArray(record.PayloadLength);
        if(payload == NULL) {
            LOGD("NFC_Set Record Payload Error\n");
            goto end;
        }

        e->SetByteArrayRegion(type, 0, record.TypeLength,
                (jbyte *)record.Type);
        e->SetByteArrayRegion(id, 0, record.IdLength,
                (jbyte *)record.Id);
        e->SetByteArrayRegion(payload, 0, record.PayloadLength,
                (jbyte *)record.PayloadData);

        new_record = e->NewObject(record_cls, ctor,
                (jshort)record.Tnf, type, id, payload);

        e->SetObjectArrayElement(records_array, i, new_record);

        /* Try not to clutter the Java stack too much */
        e->DeleteLocalRef(new_record);
        e->DeleteLocalRef(type);
        e->DeleteLocalRef(id);
        e->DeleteLocalRef(payload);
    }

    /* Store built array in our NDEFMessage instance */
    msg_cls = e->GetObjectClass(o);
    mrecords = e->GetFieldID(msg_cls, "mRecords", "[Landroid/nfc/NdefRecord;");

    e->SetObjectField(o, mrecords, (jobject)records_array);

    ret = 0;

end:
    if(is_chunked)
        free(is_chunked);
    if(records)
        free(records);
    e->ReleaseByteArrayElements(array, raw_msg, JNI_ABORT);

    return ret;
}

static JNINativeMethod gMethods[] = {
        {"parseNdefMessage", "([B)I", (void *)android_nfc_NdefMessage_parseNdefMessage},
};

int register_android_nfc_NdefMessage(JNIEnv *e)
{
    return jniRegisterNativeMethods(e, "android/nfc/NdefMessage", gMethods, NELEM(gMethods));
}

} // namespace android
