/*
 * 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 "errno.h"
#include "com_android_nfc.h"
#include "com_android_nfc_list.h"
#include "phLibNfcStatus.h"

/*
 * JNI Initialization
 */
jint JNI_OnLoad(JavaVM *jvm, void *reserved)
{
   JNIEnv *e;

   LOGD("NFC Service : loading JNI\n");

   // Check JNI version
   if(jvm->GetEnv((void **)&e, JNI_VERSION_1_6))
      return JNI_ERR;

   if (android::register_com_android_nfc_NativeNfcManager(e) == -1)
      return JNI_ERR;
   if (android::register_com_android_nfc_NativeNfcTag(e) == -1)
      return JNI_ERR;
   if (android::register_com_android_nfc_NativeP2pDevice(e) == -1)
      return JNI_ERR;
   if (android::register_com_android_nfc_NativeLlcpSocket(e) == -1)
      return JNI_ERR;
   if (android::register_com_android_nfc_NativeLlcpConnectionlessSocket(e) == -1)
      return JNI_ERR;
   if (android::register_com_android_nfc_NativeLlcpServiceSocket(e) == -1)
      return JNI_ERR;
   if (android::register_com_android_nfc_NativeNfcSecureElement(e) == -1)
      return JNI_ERR;

   return JNI_VERSION_1_6;
}

namespace android {

extern struct nfc_jni_native_data *exported_nat;

/*
 * JNI Utils
 */
bool nfc_cb_data_init(nfc_jni_callback_data* pCallbackData, void* pContext)
{
   /* Create semaphore */
   if(sem_init(&pCallbackData->sem, 0, 0) == -1)
   {
      LOGE("Semaphore creation failed (errno=0x%08x)", errno);
      return false;
   }

   /* Set default status value */
   pCallbackData->status = NFCSTATUS_FAILED;

   /* Copy the context */
   pCallbackData->pContext = pContext;

   /* Add to active semaphore list */
   if (!listAdd(&nfc_jni_get_monitor()->sem_list, pCallbackData))
   {
      LOGE("Failed to add the semaphore to the list");
   }

   return true;
}

void nfc_cb_data_deinit(nfc_jni_callback_data* pCallbackData)
{
   /* Destroy semaphore */
   if (sem_destroy(&pCallbackData->sem))
   {
      LOGE("Failed to destroy semaphore (errno=0x%08x)", errno);
   }

   /* Remove from active semaphore list */
   if (!listRemove(&nfc_jni_get_monitor()->sem_list, pCallbackData))
   {
      LOGE("Failed to remove semaphore from the list");
   }

}

void nfc_cb_data_releaseAll()
{
   nfc_jni_callback_data* pCallbackData;

   while (listGetAndRemoveNext(&nfc_jni_get_monitor()->sem_list, (void**)&pCallbackData))
   {
      pCallbackData->status = NFCSTATUS_FAILED;
      sem_post(&pCallbackData->sem);
   }
}

int nfc_jni_cache_object(JNIEnv *e, const char *clsname,
   jobject *cached_obj)
{
   jclass cls;
   jobject obj;
   jmethodID ctor;

   cls = e->FindClass(clsname);
   if(cls == NULL)
   {
      return -1;
      LOGD("Find class error\n");
   }


   ctor = e->GetMethodID(cls, "<init>", "()V");

   obj = e->NewObject(cls, ctor);
   if(obj == NULL)
   {
      return -1;
      LOGD("Create object error\n");
   }

   *cached_obj = e->NewGlobalRef(obj);
   if(*cached_obj == NULL)
   {
      e->DeleteLocalRef(obj);
      LOGD("Global ref error\n");
      return -1;
   }

   e->DeleteLocalRef(obj);

   return 0;
}


struct nfc_jni_native_data* nfc_jni_get_nat(JNIEnv *e, jobject o)
{
   jclass c;
   jfieldID f;

   /* Retrieve native structure address */
   c = e->GetObjectClass(o);
   f = e->GetFieldID(c, "mNative", "I");
   return (struct nfc_jni_native_data*)e->GetIntField(o, f);
}

struct nfc_jni_native_data* nfc_jni_get_nat_ext(JNIEnv *e)
{
   return exported_nat;
}

static nfc_jni_native_monitor_t *nfc_jni_native_monitor = NULL;

nfc_jni_native_monitor_t* nfc_jni_init_monitor(void)
{

   pthread_mutexattr_t recursive_attr;

   pthread_mutexattr_init(&recursive_attr);
   pthread_mutexattr_settype(&recursive_attr, PTHREAD_MUTEX_RECURSIVE_NP);

   if(nfc_jni_native_monitor == NULL)
   {
      nfc_jni_native_monitor = (nfc_jni_native_monitor_t*)malloc(sizeof(nfc_jni_native_monitor_t));
   }

   if(nfc_jni_native_monitor != NULL)
   {
      memset(nfc_jni_native_monitor, 0, sizeof(nfc_jni_native_monitor_t));

      if(pthread_mutex_init(&nfc_jni_native_monitor->reentrance_mutex, &recursive_attr) == -1)
      {
         LOGE("NFC Manager Reentrance Mutex creation retruned 0x%08x", errno);
         return NULL;
      }

      if(pthread_mutex_init(&nfc_jni_native_monitor->concurrency_mutex, NULL) == -1)
      {
         LOGE("NFC Manager Concurrency Mutex creation retruned 0x%08x", errno);
         return NULL;
      }

      if(!listInit(&nfc_jni_native_monitor->sem_list))
      {
         LOGE("NFC Manager Semaphore List creation retruned 0x%08x", errno);
         return NULL;
      }
   }

   return nfc_jni_native_monitor;
} 

nfc_jni_native_monitor_t* nfc_jni_get_monitor(void)
{
   return nfc_jni_native_monitor;
}
   

phLibNfc_Handle nfc_jni_get_p2p_device_handle(JNIEnv *e, jobject o)
{
   jclass c;
   jfieldID f;

   c = e->GetObjectClass(o);
   f = e->GetFieldID(c, "mHandle", "I");

   return e->GetIntField(o, f);
}

jshort nfc_jni_get_p2p_device_mode(JNIEnv *e, jobject o)
{
   jclass c;
   jfieldID f;

   c = e->GetObjectClass(o);
   f = e->GetFieldID(c, "mMode", "S");

   return e->GetShortField(o, f);
}


int nfc_jni_get_connected_tech_index(JNIEnv *e, jobject o)
{

   jclass c;
   jfieldID f;

   c = e->GetObjectClass(o);
   f = e->GetFieldID(c, "mConnectedTechnology", "I");

   return e->GetIntField(o, f);

}

jint nfc_jni_get_connected_technology(JNIEnv *e, jobject o)
{
   jclass c;
   jfieldID f;
   int connectedTech = -1;

   int connectedTechIndex = nfc_jni_get_connected_tech_index(e,o);
   jintArray techTypes = nfc_jni_get_nfc_tag_type(e, o);

   if ((connectedTechIndex != -1) && (techTypes != NULL) &&
           (connectedTechIndex < e->GetArrayLength(techTypes))) {
       jint* technologies = e->GetIntArrayElements(techTypes, 0);
       if (technologies != NULL) {
           connectedTech = technologies[connectedTechIndex];
           e->ReleaseIntArrayElements(techTypes, technologies, JNI_ABORT);
       }
   }

   return connectedTech;

}

phLibNfc_Handle nfc_jni_get_connected_handle(JNIEnv *e, jobject o)
{
   jclass c;
   jfieldID f;
   phLibNfc_Handle connectedHandle = -1;

   int connectedTechIndex = nfc_jni_get_connected_tech_index(e,o);
   c = e->GetObjectClass(o);
   f = e->GetFieldID(c, "mTechHandles", "[I");
   jintArray techHandles =  (jintArray) e->GetObjectField(o, f);

   if ((connectedTechIndex != -1) && (techHandles != NULL) &&
           (connectedTechIndex < e->GetArrayLength(techHandles))) {
       jint* handles = e->GetIntArrayElements(techHandles, 0);
       if (handles != NULL) {
           connectedHandle = handles[connectedTechIndex];
           e->ReleaseIntArrayElements(techHandles, handles, JNI_ABORT);
       }
   }
   return connectedHandle;

}

phLibNfc_Handle nfc_jni_get_nfc_tag_handle(JNIEnv *e, jobject o)
{
   jclass c;
   jfieldID f;

   c = e->GetObjectClass(o);
   f = e->GetFieldID(c, "mHandle", "I");

   return e->GetIntField(o, f);
}

phLibNfc_Handle nfc_jni_get_nfc_socket_handle(JNIEnv *e, jobject o)
{
   jclass c;
   jfieldID f;

   c = e->GetObjectClass(o);
   f = e->GetFieldID(c, "mHandle", "I");

   return e->GetIntField(o, f);
}

jintArray nfc_jni_get_nfc_tag_type(JNIEnv *e, jobject o)
{
  jclass c;
  jfieldID f;
  jintArray techtypes;
   
  c = e->GetObjectClass(o);
  f = e->GetFieldID(c, "mTechList","[I");

  /* Read the techtypes  */
  techtypes = (jintArray) e->GetObjectField(o, f);

  return techtypes;
}



//Display status code
const char* nfc_jni_get_status_name(NFCSTATUS status)
{
   #define STATUS_ENTRY(status) { status, #status }
 
   struct status_entry {
      NFCSTATUS   code;
      const char  *name;
   };

   const struct status_entry sNameTable[] = {
      STATUS_ENTRY(NFCSTATUS_SUCCESS),
      STATUS_ENTRY(NFCSTATUS_FAILED),
      STATUS_ENTRY(NFCSTATUS_INVALID_PARAMETER),
      STATUS_ENTRY(NFCSTATUS_INSUFFICIENT_RESOURCES),
      STATUS_ENTRY(NFCSTATUS_TARGET_LOST),
      STATUS_ENTRY(NFCSTATUS_INVALID_HANDLE),
      STATUS_ENTRY(NFCSTATUS_MULTIPLE_TAGS),
      STATUS_ENTRY(NFCSTATUS_ALREADY_REGISTERED),
      STATUS_ENTRY(NFCSTATUS_FEATURE_NOT_SUPPORTED),
      STATUS_ENTRY(NFCSTATUS_SHUTDOWN),
      STATUS_ENTRY(NFCSTATUS_ABORTED),
      STATUS_ENTRY(NFCSTATUS_REJECTED ),
      STATUS_ENTRY(NFCSTATUS_NOT_INITIALISED),
      STATUS_ENTRY(NFCSTATUS_PENDING),
      STATUS_ENTRY(NFCSTATUS_BUFFER_TOO_SMALL),
      STATUS_ENTRY(NFCSTATUS_ALREADY_INITIALISED),
      STATUS_ENTRY(NFCSTATUS_BUSY),
      STATUS_ENTRY(NFCSTATUS_TARGET_NOT_CONNECTED),
      STATUS_ENTRY(NFCSTATUS_MULTIPLE_PROTOCOLS),
      STATUS_ENTRY(NFCSTATUS_DESELECTED),
      STATUS_ENTRY(NFCSTATUS_INVALID_DEVICE),
      STATUS_ENTRY(NFCSTATUS_MORE_INFORMATION),
      STATUS_ENTRY(NFCSTATUS_RF_TIMEOUT),
      STATUS_ENTRY(NFCSTATUS_RF_ERROR),
      STATUS_ENTRY(NFCSTATUS_BOARD_COMMUNICATION_ERROR),
      STATUS_ENTRY(NFCSTATUS_INVALID_STATE),
      STATUS_ENTRY(NFCSTATUS_NOT_REGISTERED),
      STATUS_ENTRY(NFCSTATUS_RELEASED),
      STATUS_ENTRY(NFCSTATUS_NOT_ALLOWED),
      STATUS_ENTRY(NFCSTATUS_INVALID_REMOTE_DEVICE),
      STATUS_ENTRY(NFCSTATUS_SMART_TAG_FUNC_NOT_SUPPORTED),
      STATUS_ENTRY(NFCSTATUS_READ_FAILED),
      STATUS_ENTRY(NFCSTATUS_WRITE_FAILED),
      STATUS_ENTRY(NFCSTATUS_NO_NDEF_SUPPORT),
      STATUS_ENTRY(NFCSTATUS_EOF_NDEF_CONTAINER_REACHED),
      STATUS_ENTRY(NFCSTATUS_INVALID_RECEIVE_LENGTH),
      STATUS_ENTRY(NFCSTATUS_INVALID_FORMAT),
      STATUS_ENTRY(NFCSTATUS_INSUFFICIENT_STORAGE),
      STATUS_ENTRY(NFCSTATUS_FORMAT_ERROR),
   };

   int i = sizeof(sNameTable)/sizeof(status_entry);
 
   while(i>0)
   {
      i--;
      if (sNameTable[i].code == PHNFCSTATUS(status))
      {
         return sNameTable[i].name;
      }
   }

   return "UNKNOWN";
}

int addTechIfNeeded(int *techList, int* handleList, int listSize, int maxListSize,
        int techToAdd, int handleToAdd) {
    bool found = false;
    for (int i = 0; i < listSize; i++) {
        if (techList[i] == techToAdd) {
            found = true;
            break;
        }
    }
    if (!found && listSize < maxListSize) {
        techList[listSize] = techToAdd;
        handleList[listSize] = handleToAdd;
        return listSize + 1;
    }
    else {
        return listSize;
    }
}


#define MAX_NUM_TECHNOLOGIES 32

/*
 *  Utility to get a technology tree and a corresponding handle list from a detected tag.
 */
void nfc_jni_get_technology_tree(JNIEnv* e, phLibNfc_RemoteDevList_t* devList,
        uint8_t count, jintArray* techList, jintArray* handleList)
{
   int technologies[MAX_NUM_TECHNOLOGIES];
   int handles[MAX_NUM_TECHNOLOGIES];
   int index = 0;
   for (int target = 0; target < count; target++) {
       int type = devList[target].psRemoteDevInfo->RemDevType;
       int handle = devList[target].hTargetDev;
       switch (type)
       {
          case phNfc_eISO14443_A_PICC:
          case phNfc_eISO14443_4A_PICC:
            {
              index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES,
                      TARGET_TYPE_ISO14443_4, handle);
              index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES,
                      TARGET_TYPE_ISO14443_3A, handle);

              index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES,
                      TARGET_TYPE_NDEF_FORMATABLE, handle);
              break;
            }
          case phNfc_eISO14443_4B_PICC:
            {
              index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES,
                      TARGET_TYPE_ISO14443_4, handle);
              index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES,
                      TARGET_TYPE_ISO14443_3B, handle);
            }break;
          case phNfc_eISO14443_3A_PICC:
            {
              index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES,
                      TARGET_TYPE_ISO14443_3A, handle);
            }break;
          case phNfc_eISO14443_B_PICC:
            {
              // TODO a bug in libnfc will cause 14443-3B only cards
              // to be returned as this type as well, but these cards
              // are very rare. Hence assume it's -4B
              index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES,
                      TARGET_TYPE_ISO14443_4, handle);
              index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES,
                      TARGET_TYPE_ISO14443_3B, handle);
            }break;
          case phNfc_eISO15693_PICC:
            {
              index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES,
                      TARGET_TYPE_ISO15693, handle);
            }break;
          case phNfc_eMifare_PICC:
            {
              int sak = devList[target].psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak;
              switch(sak)
              {
                case 0x00:
                  // could be UL or UL-C
                  index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES,
                      TARGET_TYPE_MIFARE_UL, handle);
                  index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES,
                      TARGET_TYPE_ISO14443_3A, handle);
                  index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES,
                      TARGET_TYPE_NDEF_FORMATABLE, handle);
                  break;
                case 0x08:
                case 0x09:
                case 0x10:
                case 0x11:
                case 0x18:
                case 0x28:
                case 0x38:
                case 0x88:
                case 0x98:
                case 0xB8:
                  index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES,
                      TARGET_TYPE_MIFARE_CLASSIC, handle);
                  index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES,
                      TARGET_TYPE_ISO14443_3A, handle);
                  index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES,
                      TARGET_TYPE_NDEF_FORMATABLE, handle);
                  break;
                case 0x20:
                  // This could be DESfire, but libnfc returns that as ISO14443_4
                  // so we shouldn't hit this case
                default:
                  {
                    index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES,
                      TARGET_TYPE_UNKNOWN, handle);
                  }break;
              }
            }break;
          case phNfc_eFelica_PICC:
            {
              index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES,
                TARGET_TYPE_FELICA, handle);
            }break;
          case phNfc_eJewel_PICC:
            {
// TODO expose Jewel in the Java APIs
//              index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES,
//                TARGET_TYPE_JEWEL, handle);
              index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES,
                TARGET_TYPE_ISO14443_3A, handle);
            }break;
          default:
            {
              index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES,
                TARGET_TYPE_UNKNOWN, handle);
            }
        }
   }
   // Build the Java arrays
   *techList = e->NewIntArray(index);
   *handleList = e->NewIntArray(index);

   jint* techItems = e->GetIntArrayElements(*techList, NULL);
   jint* handleItems = e->GetIntArrayElements(*handleList, NULL);
   for (int i = 0; i < index; i++) {
       techItems[i] = technologies[i];
       handleItems[i] = handles[i];
   }
   e->ReleaseIntArrayElements(*techList, techItems, 0);
   e->ReleaseIntArrayElements(*handleList, handleItems, 0);

}

} // namespace android
