
package com.reactlibrary;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.UiThreadUtil;
import android.widget.Toast;  
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;

import com.mantra.mfs100.FingerData;
import com.mantra.mfs100.MFS100;
import com.mantra.mfs100.MFS100Event;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileInputStream;


public class RNMantraFingerprintScannerModule extends ReactContextBaseJavaModule implements MFS100Event{

   static {
 	System.loadLibrary("MFS100V9032");
   }

   private enum ScannerAction {
        Capture, Verify
    }

    byte[] Enroll_Template;
    byte[] Verify_Template;
    private FingerData lastCapFingerData = null;
    ScannerAction scannerAction = ScannerAction.Capture;

    int timeout = 10000;
    MFS100 mfs100 = null;

    private boolean isCaptureRunning = false;

    private final ReactApplicationContext reactContext;

    public RNMantraFingerprintScannerModule(ReactApplicationContext reactContext) {
      super(reactContext);
      this.reactContext = reactContext;
         if (mfs100 == null) {
             mfs100 = new MFS100(this);
             mfs100.SetApplicationContext(reactContext);

         }
   }

   @Override
   public String getName() {
     return "RNMantraFingerprintScanner";
   }

    private void SetTextOnUIThread(final String str) {
      Toast.makeText(reactContext, str, Toast.LENGTH_LONG).show();
    } 

    @ReactMethod
    private void GetSDKVersion(){
	SetTextOnUIThread(mfs100.GetSDKVersion());
    }

    @ReactMethod
    private void InitScanner() {
        try {
            int ret = mfs100.Init();
            if (ret != 0) {
                SetTextOnUIThread(mfs100.GetErrorMsg(ret));
            } else {
                SetTextOnUIThread("Init success");
                String info = "Serial: " + mfs100.GetDeviceInfo().SerialNo()
                        + " Make: " + mfs100.GetDeviceInfo().Make()
                        + " Model: " + mfs100.GetDeviceInfo().Model()
                        + "\nCertificate: " + mfs100.GetCertification();
            }
        } catch (Exception ex) {
            SetTextOnUIThread("Init failed, unhandled exception");
        }
    }

    @Override
    public void OnDeviceAttached(int vid, int pid, boolean hasPermission) {

        int ret;
        if (!hasPermission) {
            SetTextOnUIThread("Permission denied");
            return;
        }
        if (vid == 1204 || vid == 11279) {
            if (pid == 34323) {
                ret = mfs100.LoadFirmware();
                if (ret != 0) {
                    SetTextOnUIThread(mfs100.GetErrorMsg(ret));
                } else {
                    SetTextOnUIThread("Load firmware success");
                }
            } else if (pid == 4101) {
                String key = "Without Key";
                ret = mfs100.Init();
                if (ret == 0) {
                    SetTextOnUIThread("device attached");
                } else {
                    SetTextOnUIThread(mfs100.GetErrorMsg(ret));
                }
            }
        }
    } 
 
    @Override
    public void OnDeviceDetached() {
        SetTextOnUIThread("Device removed");
    }
    
    @Override
    public void OnHostCheckFailed(String err) {
        try {
          SetTextOnUIThread("on host check failed error");
        } catch (Exception ignored) {
        }
    }

    @ReactMethod
        private void StartSyncCapture(final Callback errorCallback,final Callback successCallback) {
    	 new Thread(new Runnable() {
			@Override
			public void run() {
                isCaptureRunning = true;
		        try {
		            FingerData fingerData = new FingerData();
		            final int ret = mfs100.AutoCapture(fingerData, timeout,false);
		            if (ret != 0) {
		            UiThreadUtil.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(getReactApplicationContext(),mfs100.GetErrorMsg(ret),Toast.LENGTH_LONG).show();
                        }
                    });
		            } else {
		               /* lastCapFingerData = fingerData;
		                final Bitmap bitmap = BitmapFactory.decodeByteArray(fingerData.FingerImage(), 0,
		                        fingerData.FingerImage().length); */
		            UiThreadUtil.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(getReactApplicationContext(),"capture success",Toast.LENGTH_LONG).show();
                        }
                    });
                   
                    long unixTime = System.currentTimeMillis() / 1000L;
                    String filename = unixTime+"fingerISO.iso";
                    WriteFile(filename,fingerData.ISOTemplate()); 
 
                    successCallback.invoke(filename);

                    
                   /* Verify_Template = new byte[fingerData.ISOTemplate().length];
                    System.arraycopy(fingerData.ISOTemplate(), 0, Verify_Template, 0,
                            fingerData.ISOTemplate().length);
                    WriteFile("verifytemplate.iso",Verify_Template); 
                    successCallback.invoke(Environment.getExternalStorageDirectory() + "//FingerData" + "//" + filename);
                    */                    

                    /* Stiring Conversion and matchening 
                    Enroll_Template = new byte[fingerData.ISOTemplate().length];
                    System.arraycopy(fingerData.ISOTemplate(), 0, Enroll_Template, 0,
                            fingerData.ISOTemplate().length);
                    String btos = new String(Enroll_Template, "UTF-8");
                    byte[] stob = btos.getBytes("UTF-8"); 

                    int ret1 = mfs100.MatchISO(fingerData.ISOTemplate(),stob);
                    successCallback.invoke(ret1); */


                    /* Read iso file and compare
                    
                    long unixTime = System.currentTimeMillis() / 1000L;
                    String filename = unixTime+"fingerISO.iso";
                    WriteFile(filename,fingerData.ISOTemplate()); 

                    byte[] convertem = ReadFile("verifytemplate.iso");
                    byte[] confingeriso = ReadFile("fingerISO.iso");

                    if(convertem.length > 0 && confingeriso.length > 0){
                    int ret1 = mfs100.MatchISO(convertem,confingeriso);
                    if(ret1 > 1400 ){
                        successCallback.invoke(ret1);
                    }else{
                        successCallback.invoke("un-matched");
                    }
                    } 
                    successCallback.invoke(Environment.getExternalStorageDirectory() + "//FingerData" + "//" + filename);
                */
                } 
		        } catch (Exception ex) {
                    SetTextOnUIThread("Error");
                    errorCallback.invoke("failure");
		        } finally {
                    isCaptureRunning = false;
                }
            }
		}).start(); 
    }

    private void WriteFile(String filename, byte[] bytes) {
        try {
            String path = Environment.getExternalStorageDirectory()
                    + "//FingerData";
            File file = new File(path);
            if (!file.exists()) {
                file.mkdirs();
            }
            path = path + "//" + filename;
            file = new File(path);
            if (!file.exists()) {
                file.createNewFile();
            }
            FileOutputStream stream = new FileOutputStream(path);
            stream.write(bytes);
            stream.close();
        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }

    private byte[] ReadFile(String filename){
        try {
            String path = Environment.getExternalStorageDirectory() + "//FingerData" + "//" + filename;
            File file = new File(path);
            byte[] bytesArray = new byte[(int) file.length()]; 

            FileInputStream fis = new FileInputStream(file);
            fis.read(bytesArray); //read file into bytes[]
            fis.close();
                      
            return bytesArray;
            
        } catch (Exception e1) {
           return new byte[0];
        }
    }
    @ReactMethod
        private void compareFingerPrintByISO(final String isoFileName,final Callback errorCallback,final Callback successCallback) {
    	 new Thread(new Runnable() {
			@Override
			public void run() {
                isCaptureRunning = true;
		        try {
		            FingerData fingerData = new FingerData();
		            final int ret = mfs100.AutoCapture(fingerData, timeout,false);
		            if (ret != 0) {
		            UiThreadUtil.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(getReactApplicationContext(),mfs100.GetErrorMsg(ret),Toast.LENGTH_LONG).show();
                        }
                    });
		            } else {
		            UiThreadUtil.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(getReactApplicationContext(),"Capture Success",Toast.LENGTH_LONG).show();
                        }
                    });

                    byte[] confingeriso = ReadFile(isoFileName);
                    int ret1 = mfs100.MatchISO(confingeriso,fingerData.ISOTemplate());
                    if(ret1 > 1400 ){
                        successCallback.invoke("matched");
                    }else{
                        successCallback.invoke("un-matched");
                    }
                } 
		        } catch (Exception ex) {
                    SetTextOnUIThread("Error");
                    errorCallback.invoke("failure");
		        } finally {
                    isCaptureRunning = false;
                }
            }
		}).start(); 
    }
    
}
