/*
 * Copyright (c) 2017 Oracle and/or its affiliates.  All rights reserved.
 *
 * This software is dual-licensed to you under the MIT License (MIT) and 
 * the Universal Permissive License (UPL).  See the LICENSE file in the root
 * directory for license terms.  You may choose either license, or both.
 */

package com.oracle.iot.sample;

import android.content.Intent;
import android.location.Location;
import android.nfc.*;
import android.nfc.tech.Ndef;
import android.util.Log;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

/**
 * Proximity NFCSensor queues the NFC tag values that are consumed by NFC Gateway service,
 * which sends the value to IoT CS.
 */
class NFCSensor {

    class TagData {
        String tagSerialNumber;
        String tagManufacturer;
        String tagModelNumber;
        Location location;
    }

    private final BlockingQueue<TagData> tagQueue;
    private static NFCSensor instance;
    private static int MAX_TAG_QUEUE_SIZE = 64;

    private NFCSensor() {
        tagQueue = new ArrayBlockingQueue<>(MAX_TAG_QUEUE_SIZE);

    }

    static NFCSensor getInstance() {
        if (instance == null) {
            instance = new NFCSensor();
        }
        return instance;
    }
    String getTagSerialNumber(byte[] tagId) {
        StringBuilder sb = new StringBuilder("");
        int len = tagId.length;
        for (int i=0; i < len-1; i++) {
                sb.append(String.format("%02X:", tagId[i]));
        }
        sb.append(String.format("%02X", tagId[len-1]));
        return sb.toString();
    }

    boolean isProximityIntent(Intent intent) {
        String action = intent.getAction();
        return  (action != null &&
                 (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action) ||
                  NfcAdapter.ACTION_TECH_DISCOVERED.equals(action) ||
                  NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)));
    }

    void processTagFound(Tag tag, Location location) {
        try {
            TagData tagData = new TagData();
            byte tagId[] = tag.getId();
            if (tagId == null || tagId.length == 0) {
                Log.d("NFC", "Empty Tag serial number. Ignoring the TAG..");
                return;
            }
            List techList = Arrays.asList(tag.getTechList());
            if (techList.contains("android.nfc.tech.NfcA") &&  tagId.length == 7) {
                // For NfcA tags which have 7 byte UID, the first byte has manufacturer ID.
                tagData.tagManufacturer = getTagManufacturerName(tagId[0]);
            } else if (techList.contains("android.nfc.tech.NfcV") &&  tagId.length == 8){
                // For NfcV tags which have 7 byte UID, the first byte has manufacturer ID.
                tagData.tagManufacturer = getTagManufacturerName(tagId[1]);
            } else {
                tagData.tagManufacturer = "Unknown";
            }
            tagData.tagModelNumber = getTagModel(tag);
            tagData.tagSerialNumber = getTagSerialNumber(tag.getId());
            tagData.location = location;
            tagQueue.put(tagData);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    TagData getNextTagData() {
        TagData tagData = null;
        try {
            tagData = tagQueue.take();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return tagData;
    }

    private String getTagManufacturerName(byte manufactureId) {
        if (manufactureId < manufacturerList.length) {
            return manufacturerList[manufactureId];
        } else {
            return "Unkown";
        }
    }

    private String getTagModel(Tag tag) {
        Ndef ndefTag =  Ndef.get(tag);
        String model = "Unknown";
        if (ndefTag != null ) {
            model = ndefTag.getType();
        }
        return model;
    }

    // List of NFC tag manufacturers.
    // The list is formed from the information here.
    // http://isotc.iso.org/livelink/livelink/fetch/-8915513/8915538/8915579/ISO_IEC_JTC1_SC17_Standing_Document_5_Register_of_IC_Manufacturers.pdf?nodeid=10432471&vernum=-2
    private static final String manufacturerList[] = {
        "Unknown",
        "Motorola UK",
        "STMicroelectronics SA France",
        "Hitachi, Ltd Japan",
        "NXP Semiconductors Germany",
        "Infineon Technologies AG Germany",
        "Cylink USA",
        "Texas Instrument France",
        "Fujitsu Limited Japan",
        "Matsushita Electronics Corporation, Semiconductor Company Japan",
        "NEC Japan",
        "Oki Electric Industry Co. Ltd Japan",
        "Toshiba Corp. Japan",
        "Mitsubishi Electric Corp. Japan",
        "Samsung Electronics Co. Ltd Korea",
        "Hynix Korea",
        "LG-Semiconductors Co. Ltd Korea",
        "Emosyn-EM Microelectronics USA",
        "INSIDE Technology France",
        "ORGA Kartensysteme GmbH Germany",
        "SHARP Corporation Japan",
        "ATMEL France",
        "EM Microelectronic-Marin SA Switzerland",
        "SMARTRAC TECHNOLOGY GmbH Germany",
        "ZMD AG Germany",
        "XICOR, Inc. USA",
        "Sony Corporation Japan",
        "Identifier Company Country",
        "Malaysia Microelectronic Solutions Sdn. Bhd Malaysia",
        "Emosyn USA",
        "Shanghai Fudan Microelectronics Co. Ltd. P.R. China",
        "Magellan Technology Pty Limited Australia",
        "Melexis NV BO Switzerland",
        "Renesas Technology Corp. Japan",
        "TAGSYS France",
        "Transcore USA",
        "Shanghai belling corp., ltd. China",
        "Masktech Germany Gmbh Germany",
        "Innovision Research and Technology Plc UK",
        "Hitachi ULSI Systems Co., Ltd. Japan",
        "Yubico AB Sweden",
        "Ricoh Japan",
        "ASK France",
        "Unicore Microsystems, LLC Russian",
        "Federation",
        "Dallas Semiconductor/Maxim USA",
        "Impinj, Inc. USA",
        "RightPlug Alliance USA",
        "Broadcom Corporation USA",
        "MStar Semiconductor, Inc Taiwan, ROC",
        "BeeDar Technology Inc. USA",
        "RFIDsec Denmark",
        "Schweizer Electronic AG Germany",
        "AMIC Technology Corp Taiwan",
        "Mikron JSC Russia",
        "Fraunhofer Institute for Photonic Microsystems Germany",
        "IDS Microchip AG Switzerland",
        "Kovio USA",
        "HMT Microelectronic Ltd Switzerland",
        "Silicon Craft Technology Thailand",
        "Identifier Company Country",
        "Advanced Film Device Inc. Japan",
        "Nitecrest Ltd UK",
        "Verayo Inc. USA",
        "HID Global USA",
        "Productivity Engineering Gmbh Germany",
        "Austriamicrosystems AG (reserved) Austria",
        "Gemalto SA France",
        "Renesas Electronics Corporation Japan",
        "3Alogics Inc Korea",
        "Top TroniQ Asia Limited Hong Kong",
        "Gentag Inc (USA) USA",
        "Invengo Information Technology Co.Ltd China",
        "Guangzhou Sysur Microelectronics, Inc China",
        "CEITEC S.A. Brazil",
        "Shanghai Quanray Electronics Co. Ltd. China",
        "MediaTek Inc Taiwan",
        "Angstrem PJSC Russia",
        "Celisic Semiconductor (Hong Kong) Limited China",
        "LEGIC Identsystems AG Switzerland",
        "Balluff GmbH Germany",
        "Oberthur Technologies France",
        "Silterra Malaysia Sdn. Bhd. Malaysia",
        "DELTA Danish Electronics, Light & Acoustics Denmark",
        "Giesecke & Devrient GmbH Germany",
        "Shenzhen China Vision Microelectronics Co., Ltd. China",
        "Shanghai Feiju Microelectronics Co. Ltd. China",
        "Intel Corporation USA",
        "Microsensys GmbH Germany",
        "Sonix Technology Co., Ltd. Taiwan",
        "Qualcomm Technologies Inc USA",
        "Realtek Semiconductor Corp Taiwan",
        "Identifier Company Country",
        "Freevision Technologies Co. Ltd China",
        "Giantec Semiconductor Inc. China",
        "JSC Angstrem-T Russia",
        "STARCHIP France",
        "SPIRTECH France",
        "GANTNER Electronic GmbH Austria",
        "Nordic Semiconductor Norway",
        "Verisiti Inc USA",
        "Wearlinks Technology Inc. China",
        "Userstar Information Systems Co., Ltd Taiwan",
        "Pragmatic Printing Ltd. UK",
        "Associação do Laboratório de Sistemas Integráveis Tecnológico",
        "I-TEC Brazil",
        "Tendyron Corporation China",
        "MUTO Smart Co., Ltd. Korea",
        "ON Semiconductor USA",
        "TÜBİTAK BİLGEM Turkey",
        "Huada Semiconductor Co., Ltd China",
        "SEVENEY France",
        "ISSM France",
        "Wisesec Ltd Israel",
    };
}

