package com.fingerprint.reader.test;

import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;

import com.fpreader.fpdevice.Constants;
import com.fpreader.fpdevice.UsbReader;

import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.text.format.Time;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class UsbTest1Activity extends AppCompatActivity {

    private UsbReader fpModule;

    private boolean isopening=false;
    private boolean isworking=false;
    private boolean isautocap=false;

    private TextView tvStatus=null;
    private TextView tvResult=null;
    private ImageView ivImage=null;
    private Button buttonOpenDevice,buttonCloseDevice,buttonEnrol,buttonMatch;

    private byte bmpdata[]=new byte[UsbReader.FAP10_BMP_SIZE];
    private int bmpsize[]=new int[1];
    private byte refdata[][]=new byte[1024][UsbReader.TP_SIZE_REF];
    private int refsize[]=new int[1];
    private int refcount=0;
    private byte matdata[]=new byte[512];
    private int matsize[]=new int[1];

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_usb_test1);

        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.test1), (v, insets) -> {
            Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
            return insets;
        });

        buttonOpenDevice=(Button)findViewById(R.id.buttonOpenDevice);
        buttonCloseDevice=(Button)findViewById(R.id.buttonCloseDevice);
        buttonEnrol=(Button)findViewById(R.id.buttonEnrol);
        buttonMatch=(Button)findViewById(R.id.buttonMatch);
        tvStatus=(TextView)findViewById(R.id.textView1);
        tvResult=(TextView)findViewById(R.id.textView2);
        ivImage=(ImageView)findViewById(R.id.imageView1);

        fpModule=new UsbReader();
        fpModule.InitMatch();
        fpModule.SetContextHandler(this,mHandler);

        buttonOpenDevice.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                if(fpModule.OpenDevice()==0){
                    tvStatus.setText(getString(R.string.txt_opendeviceok));
                    isopening=true;
                    isworking=false;
                }else{
                    //fpModule.requestPermission();
                    //tvStatus.setText(getString(R.string.txt_requestpermission));
                    tvStatus.setText(getString(R.string.txt_opendevicefail));
                }
            }
        });

        buttonCloseDevice.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                fpModule.CloseDevice();
                tvStatus.setText(getString(R.string.txt_closedevice));
            }
        });


        buttonEnrol.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                if(isopening){
                    if(isworking) return;
                    //fpModule.SetFullDetect(true,100);
                    fpModule.EnrolTemplate();
                    isworking=true;
                }
            }
        });

        buttonMatch.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                if(isopening){
                    if(isautocap){
                        isworking=false;
                        isautocap=false;
                        SetButtonsStatus(true);
                        fpModule.StopWork();
                        tvStatus.setText(R.string.txt_status);
                    }else {
                        if(isworking)
                            return;
                        isworking=true;
                        isautocap=true;
                        SetButtonsStatus(false);
                        //fpModule.SetFullDetect(false,100);
                        fpModule.GenerateTemplate();
                    }
                }
            }
        });

        fpModule.ResumeRegister();
        fpModule.requestPermission();

    }

    private void SetButtonsStatus(boolean enable){
        if(enable){
            buttonOpenDevice.setEnabled(true);
            buttonCloseDevice.setEnabled(true);
            buttonEnrol.setEnabled(true);
            buttonMatch.setEnabled(true);
            buttonMatch.setText(R.string.txt_MatchTemplate);
        }
        else{
            buttonOpenDevice.setEnabled(false);
            buttonCloseDevice.setEnabled(false);
            buttonEnrol.setEnabled(false);
            buttonMatch.setEnabled(true);
            buttonMatch.setText(R.string.txt_StopCapture);
        }
    }

    @Override
    protected void onDestroy(){
        super.onDestroy();
        if(isopening)
            fpModule.CloseDevice();
        fpModule.PauseUnRegister();
    }

    @SuppressLint("HandlerLeak")
    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg){
            switch (msg.what){
                case Constants.FPM_DEVICE:{
                    switch(msg.arg1){
                        case Constants.DEV_ATTACHED:
                            break;
                        case Constants.DEV_DETACHED:
                            isopening=false;
                            isworking=false;
                            fpModule.CloseDevice();
                            tvStatus.setText(getString(R.string.txt_closedevice));
                            break;
                        case Constants.DEV_OK:
                            isopening=true;
                            isworking=false;
                            tvStatus.setText(getString(R.string.txt_opendeviceok));
                            break;
                        default:
                            tvStatus.setText(getString(R.string.txt_opendevicefail));
                            break;
                    }
                }
                break;
                case Constants.FPM_PLACE:
                    tvStatus.setText(getString(R.string.txt_placfinger));
                    break;
                case Constants.FPM_LIFT:
                    tvStatus.setText(getString(R.string.txt_liftfinger));
                    break;
                case Constants.FPM_IMGCHECK:
                    tvStatus.setText(getString(R.string.txt_fpimagecheck));
                    break;
                case Constants.FPM_CAPTURE:{
                    if(msg.arg1==1){
                        tvStatus.setText(getString(R.string.txt_captureimageok));
                    }else{
                        tvStatus.setText(getString(R.string.txt_captureimagefail));
                    }
                    isworking=false;
                }
                break;
                case Constants.FPM_GENCHAR:{
                    if(msg.arg1==1){
                        tvStatus.setText(getString(R.string.txt_generatetemplateok));
                        fpModule.GetTemplateByGen(matdata, matsize);

                        if(refcount>0){
                            boolean bfind=false;
                            for(int i=0;i<refcount;i++){

                                int sc=fpModule.MatchTemplateOne(refdata[i],UsbReader.TP_SIZE_REF,matdata);
                                if(sc>=50) {
                                    bfind = true;
                                    tvResult.setText(String.format(getString(R.string.txt_matchok), i));
                                    break;
                                }
                            }
                            if(!bfind){
                                tvResult.setText(getString(R.string.txt_matchfail));
                            }
                        }
                    }else{
                        tvStatus.setText(getString(R.string.txt_generatetemplatefail));
                    }
                    if(isautocap) {
                        fpModule.GenerateTemplate();
                    }
                    else {
                        isworking = false;
                    }
                }
                break;
                case Constants.FPM_ENRFPT:{
                    if(msg.arg1==1){
                        fpModule.GetTemplateByEnl(refdata[refcount],refsize);
                        tvStatus.setText(getString(R.string.txt_enroltemplateok)+" "+String.valueOf(refcount));
                        refcount++;
                    }else{
                        tvStatus.setText(getString(R.string.txt_enroltemplatefail));
                    }
                    isworking=false;
                }
                break;
                case Constants.FPM_NEWIMAGE:{
                    fpModule.GetBmpImage(bmpdata,bmpsize);
                    //8Bit
                    Bitmap bm1= BitmapFactory.decodeByteArray(bmpdata, 0, bmpsize[0]);
                    //32Bit
                    //Bitmap bm1= fpModule.Bitmap8toBitmap32(bmpdata,fpModule.ImageWidth,fpModule.ImageHeight);
                    ivImage.setImageBitmap(bm1);
                }
                break;
                case Constants.FPM_TIMEOUT:
                    tvStatus.setText("Time Out");
                    isworking=false;
                    isautocap=false;
                    SetButtonsStatus(true);
                    break;
            }
        }
    };

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        // getMenuInflater().inflate(R.menu.system, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        switch(id){
            case android.R.id.home:
                this.setResult(1);
                this.finish();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    private void SaveImage(Bitmap image){
        String storageDir = Environment.getExternalStorageDirectory().getPath().toString();
        //String curPath=storageDir+"/Fingerprint";
        String curPath=storageDir+"/FPS";
        File file = new File(curPath);
        if (!file.exists()) {
            curPath=storageDir+"/"+Environment.DIRECTORY_PICTURES;
        }

        Toast.makeText(this, curPath+"/"+getDataTimeForID()+".png", Toast.LENGTH_LONG).show();

        File f = new File(curPath+"/"+getDataTimeForID()+".png");
        if (f.exists()) {
            f.delete();
        }
        try {
            FileOutputStream out = new FileOutputStream(f);
            image.compress(Bitmap.CompressFormat.PNG, 100, out);
            out.flush();
            out.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        /*
        f = new File(curPath+"/"+getDataTimeForID()+editText1.getText().toString()+".jpg");
        if (f.exists()) {
            f.delete();
        }
        try {
            FileOutputStream out = new FileOutputStream(f);
            image.compress(Bitmap.CompressFormat.JPEG, 90, out);
            out.flush();
            out.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        */
    }

    public static String getDataTimeForID(){
        Time t=new Time();
        t.setToNow();
        int year = t.year;
        int month = t.month+1;
        int date = t.monthDay;
        int hour = t.hour;
        int minute = t.minute;
        int second = t.second;
        return String.format("%d%02d%02d%02d%02d%02d",year,month,date,hour,minute,second);
    }
}
