package gen2wave.rp70biodemo.iccardnfc;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.amarula.gen2wave.sdk.usbaccessory.AccessoryPower;
import com.gemalto.gempcsc.GemErrors;
import com.gemalto.gempcsc.GemPCSC_Reader;
import com.gemalto.gempcsc.IGemPCSC;


import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Method;

import gen2wave.rp70biodemo.R;

/**
 * Created by mastyle on 17. 10. 18.
 */
public class ICcardNFCMain extends Activity implements View.OnClickListener{

    private final String TAG = "ICcardNFCMain";

    TextView icCardValueTxt = null, icCardStatusTxt = null;
    TextView nfcTypeValueTxt = null, nfcSerialValueTxt = null;

    Button readICCardBtn = null;

    private boolean mIsSerialMode = false;
    private boolean mIsBound = false;
    private boolean mIsRetry = false;
    private int sessionID = 0;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.iccard_nfc_main);
        NfcAdapter mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
        if (mNfcAdapter == null) {
            Toast.makeText(this, "This device doesn't support NFC.", Toast.LENGTH_LONG).show();
            finish();
        }

        set_smart_powerEnabled(true);

        icCardValueTxt = (TextView) findViewById(R.id.iccard_value_txt);
        icCardStatusTxt = (TextView) findViewById(R.id.iccard_status_txt);
        nfcTypeValueTxt = (TextView) findViewById(R.id.nfc_type_value_txt);
        nfcSerialValueTxt = (TextView) findViewById(R.id.nfc_serial_value_txt);
        readICCardBtn = (Button) findViewById(R.id.read_iccard_btn);
        readICCardBtn.setOnClickListener(this);



    }

    @Override
    protected void onResume() {
        super.onResume();
        Intent intent = new Intent(getApplicationContext(), this.getClass());
        intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
                intent, PendingIntent.FLAG_UPDATE_CURRENT);
        NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this);
        adapter.enableForegroundDispatch(this, pendingIntent, null, null);
    }

    @Override
    protected void onPause() {
        super.onPause();
        if(NfcAdapter.getDefaultAdapter(this) != null) {
            NfcAdapter.getDefaultAdapter(this).disableForegroundDispatch(this);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.e(TAG, "onDestroy");


        if (mIsBound) {
            if (gemPCSC_Service != null && sessionID != 0) {
                try {
                    Log.d(TAG, "GemPCSC_Finalize");
                    gemPCSC_Service.GemPCSC_Finalize(sessionID);
                    gemPCSC_Service = null;
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }

            Log.d(TAG, "unbindService");
            unbindService(serviceConnection);
        }
        set_smart_powerEnabled(false);
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        resolveIntent(intent);
    }

    void resolveIntent(Intent intent){
        String action = intent.getAction();
        Log.d(TAG, "resolveIntent action : " + action);

        if(action.equals(NfcAdapter.ACTION_NDEF_DISCOVERED) ||
                action.equals(NfcAdapter.ACTION_TAG_DISCOVERED) ||
                action.equals(NfcAdapter.ACTION_TECH_DISCOVERED)) {

            Tag mytag = (Tag) intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);

            Log.d(TAG, "TAG describeContents : " + mytag.describeContents());
            Log.d(TAG, "TAG id : " + byteArrayToIdString(mytag.getId()));

            nfcSerialValueTxt.setText(byteArrayToIdString(mytag.getId()));

            if (mytag != null) {
                for (int i = 0; i < mytag.getTechList().length; i++) {
                    String tech = mytag.getTechList()[i];
                    tech = tech.substring(tech.lastIndexOf(".")+1, tech.length());
                    Log.e(TAG, "resolveIntent tech : " + tech);

                    if (tech.equals("MifareUltralight")) {
                        nfcTypeValueTxt.setText("MifareUltralight");
                    } else if (tech.equals("MifareClassic")) {
                        nfcTypeValueTxt.setText("MifareClassic");
                    } else if (tech.equals("NfcA")) {
                        nfcTypeValueTxt.setText("NfcA");
                    } else if (tech.equals("NfcB")) {
                        nfcTypeValueTxt.setText("NfcB");
                    }else if (tech.equals("NdefFormatable")) {
                        nfcTypeValueTxt.setText("NdefFormatable");
                    } else if (tech.equals("Ndef")) {
                        nfcTypeValueTxt.setText("Ndef");
                    } else {
                        nfcTypeValueTxt.setText("Unknown Type");
                    }
                }
            }
            //			* NfcA (also known as ISO 14443-3A)
            //			* NfcB (also known as ISO 14443-3B)
            //			* NfcF (also known as JIS 6319-4)
            //			* NfcV (also known as ISO 15693)
            //			* IsoDep
            //			* Ndef on NFC Forum Type 1, Type 2, Type 3 or Type 4 compliant tags
            //			But also optionally: 
            //			* MifareClassic
            //			* MifareUltralight
        }
    }

    public static String byteArrayToIdString(byte[] array) {
        StringBuffer hexString = new StringBuffer();
        int count = 0;
        for (byte b : array) {
            int intVal = b & 0xff;
            if (intVal < 0x10)
                hexString.append("0");
            hexString.append(Integer.toHexString(intVal));
            count++;
            if (count != array.length) {
                hexString.append(":");
            }
        }
        return hexString.toString();
    }

    private void bindGemPCSC_ServiceApk() {
        Intent intentService = new Intent("com.gemalto.gempcsc.service.action");
        intentService.setPackage("com.gemalto.gempcsc.gempcscserviceactivity");
        this.bindService(intentService, serviceConnection, Context.BIND_AUTO_CREATE);
    }

    private IGemPCSC gemPCSC_Service = null;

    final ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceDisconnected(ComponentName name) {
            // on service disconnected
            Log.i(TAG, "Service disconnected");
        }
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // on service connected
            // ready to use IGemPCSC interface
            gemPCSC_Service = IGemPCSC.Stub.asInterface(service);
            mIsBound = true;
            mIsRetry = false;
            Log.i(TAG, "Service connected");
        }
    };

    private void usbGetUID() {
        try {
            if (!mIsBound) {
                return;
            }
            if (mIsBound && sessionID == 0) {
                sessionID = gemPCSC_Service.GemPCSC_Initialize();
            }

            final GemPCSC_Reader[] usbReaders = gemPCSC_Service.GemPCSC_ListReaders(sessionID);
            if (usbReaders.length == 0) {
                icCardValueTxt.setText("");
                icCardStatusTxt.setText("Check Card Reader");
                return;
            }

            final byte[] ATR = gemPCSC_Service.GemPCSC_Connect(sessionID, usbReaders[0]);
            if (!gemPCSC_Service.GemPCSC_IsCardPresent(sessionID)) {
                icCardValueTxt.setText("");
                if (ATR[1] == 0) {//[65, 0]
                    icCardStatusTxt.setText("No Card");
                } else {//[65, -2]
                    icCardStatusTxt.setText("No Card");
                }
                gemPCSC_Service.GemPCSC_Disconnect(sessionID);
                gemPCSC_Service.GemPCSC_Finalize(sessionID);
                sessionID = 0;
                unbindService(serviceConnection);
                mIsBound = false;
                gemPCSC_Service = null;
                return;
            }
            if (GemErrors.GE_OK == gemPCSC_Service.GemPCSC_GetLastError()) {
                // display ATR...
                String strtv1 ="ATR:";
                for (int i = 0; i < ATR.length; i++) {
                    strtv1 += String.format("0x%02x ", ATR[i]);
                }
                icCardValueTxt.setText(strtv1);
                icCardStatusTxt.setText("Read OK");
            }
            boolean isRet = gemPCSC_Service.GemPCSC_Disconnect(sessionID);
            if (GemErrors.GE_OK == gemPCSC_Service.GemPCSC_GetLastError()) {
            }

        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @SuppressLint("HandlerLeak")
    private Handler mHandler = new Handler()
    {
        @Override
        public void handleMessage(Message msg)
        {
            if (!mIsSerialMode) {
                return;
            }
        }
    };

    public static String getProperty(String prop) {
        String serialnum = "";

        try {
            Class<?> c = Class.forName("android.os.SystemProperties");
            Method get = c.getMethod("get", String.class, String.class );
            serialnum = (String)(   get.invoke(c, prop, "-" )  );
        }
        catch (Exception ignored)
        {
        }
        return serialnum;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.read_iccard_btn:
                icCardValueTxt.setText("");
                if (!mIsRetry && !mIsSerialMode) {
                    if (mIsBound) {
                        usbGetUID();
                    } else {
                        bindGemPCSC_ServiceApk();
                        mIsRetry = true;
                    }
                }
                break;
        }
    }

    private void set_smart_powerEnabled(boolean enabled) {
        AccessoryPower.setPower(this, AccessoryPower.AccessoryType.SMARTCARD, enabled);
    }
}
