package com.example.myapplication;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;

import org.opencv.android.CameraBridgeViewBase;
import org.opencv.core.Point;

import com.example.myapplication.databinding.ActivityMainBinding;
import com.meridianinno.libsenxor_android.BuildConfig;
import com.meridianinno.libsenxor_android.SenXorView;

import java.util.ArrayList;
import java.util.List;

/**
 *  Example 3 implements perspective transform that applies on thermal image on top of built-in camera
 *  The most convenient way is directly overlapping with simple translation,scaling and rotation
 *  MyGLSurfaceView handles the buint-in camera image and perspective transformation once the homography has set
 *  The distance between device and object affects the transformation.
 *  It requires accurate coordination mapping on both RGB image and thermal image
 *  The expected results are shown on demo.jpg and demo1.png in res/drawable/
 *
 *  Prequisite: Please import OpenCV android-sdk with jni as a third party dependency. Default version 4.3.0
 *  https://sourceforge.net/projects/opencvlibrary/files/4.3.0/opencv-4.3.0-android-sdk.zip/download
 *
 *  Arthor: Jackson LAU
 *  SDK Version: v3.2.0
 */

public class MainActivity extends Activity {
    // Used to load the 'native-lib' and 'opencv' libraries on application startup.
    static {
        System.loadLibrary("native-lib");
    }
    private ActivityMainBinding mSdk3MainBinding;

    private static final String LOG_TAG = "MainActivity";
    private static final int MY_PERMISSIONS_REQUEST_CAMERA = 1337;
    private int glSurface_width = 1280/2;
    private int glSurface_height = 920/2;

    private boolean isTakePts = true;
    private boolean mUseFrontCam = true;
    private List<Point> rgbpts_list, thermalpts_list;
    private PointAdapter rgblist_Adapter, thermallist_Adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        //Binding setup
        this.mSdk3MainBinding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(this.mSdk3MainBinding.getRoot());

        // Check for camera permissions
        final Context context = getApplicationContext();
        if(checkSelfPermission(context, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)
        {
            // Permission is not granted
            // Should we show an explanation?
            if (this.shouldShowRequestPermissionRationale(Manifest.permission.CAMERA))
            {
                // Show some text
                Toast.makeText(context, getString(R.string.MSG_PERMIT_CAMERA), Toast.LENGTH_LONG).show();
                this.finish();
            }
            else
            {
                // No explanation needed; request the permission
                this.requestPermissions(new String[]{Manifest.permission.CAMERA}, MY_PERMISSIONS_REQUEST_CAMERA);
            }
        }

        // RGB coordinates list view
        rgbpts_list = new ArrayList<Point>();
        rgblist_Adapter = new PointAdapter(this, android.R.layout.simple_expandable_list_item_1, rgbpts_list);
        mSdk3MainBinding.listviewRgbpts.setAdapter(rgblist_Adapter);

        // Thermal coordinates list view
        thermalpts_list = new ArrayList<Point>();
        thermallist_Adapter = new PointAdapter(this, android.R.layout.simple_expandable_list_item_1, thermalpts_list);
        mSdk3MainBinding.listviewThermalpts.setAdapter(thermallist_Adapter);

        // Setup GL Surface
        mSdk3MainBinding.myGlSurfaceView.setMaxCameraPreviewSize(glSurface_width, glSurface_height);
        mSdk3MainBinding.myGlSurfaceView.setCameraTextureListener(mSdk3MainBinding.myGlSurfaceView);
        mSdk3MainBinding.myGlSurfaceView.setCameraIndex(CameraBridgeViewBase.CAMERA_ID_FRONT);

        // Setup event handler
        Sdk3ClickListener tSdk3ClickListener = new Sdk3ClickListener();
        Sdk3TouchListener tSdk3TouchListener = new Sdk3TouchListener();

        mSdk3MainBinding.buttonTransform.setOnClickListener(tSdk3ClickListener);
        mSdk3MainBinding.buttonTakepts.setOnClickListener(tSdk3ClickListener);
        mSdk3MainBinding.cameraSwitch.setOnClickListener(tSdk3ClickListener);
        mSdk3MainBinding.myGlSurfaceView.setOnTouchListener(tSdk3TouchListener);
        mSdk3MainBinding.textClear.setOnClickListener(tSdk3ClickListener);
        mSdk3MainBinding.imageViewThermal.setOnTouchListener(tSdk3TouchListener);

    }


    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults)
    {
        switch (requestCode)
        {
            case MY_PERMISSIONS_REQUEST_CAMERA:
            {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    //Permission granted
                }
            }
        }
    }

    @Override
    protected void onResume()
    {
        super.onResume();
        mSdk3MainBinding.myGlSurfaceView.onResume();
        mSdk3MainBinding.imageViewThermal.setup();
        mSdk3MainBinding.imageViewThermal.start();

    }


    @Override
    public void onPause()
    {
        super.onPause();
        mSdk3MainBinding.myGlSurfaceView.onPause();
        mSdk3MainBinding.imageViewThermal.stop();

    }

    private static int checkSelfPermission(Context context, String permission)
    {
        if (permission == null)
        {
            throw new IllegalArgumentException("permission is null");
        }
        return context.checkPermission(permission, android.os.Process.myPid(), android.os.Process.myUid());
    }

    private class Sdk3ClickListener implements View.OnClickListener
    {
        @Override
        public void onClick(View view)
        {
            final int tId = view.getId();

            if(tId == R.id.button_takepts)
            {
                if (isTakePts)
                {
                    mSdk3MainBinding.buttonTakepts.setText(getString(R.string.BTN_TKE_PT_OFF));
                    mSdk3MainBinding.myGlSurfaceView.setOnTouchListener(null);
                    mSdk3MainBinding.imageViewThermal.setOnTouchListener(null);
                }
                else
                {
                    mSdk3MainBinding.buttonTakepts.setText(getString(R.string.BTN_TKE_PT_EN));
                    mSdk3MainBinding.myGlSurfaceView.setOnTouchListener( new Sdk3TouchListener());
                    mSdk3MainBinding.imageViewThermal.setOnTouchListener(new Sdk3TouchListener());
                }

                isTakePts = !isTakePts;
            }

            if(tId == R.id.text_clear)
            {
                rgbpts_list.clear();
                rgblist_Adapter.notifyDataSetChanged();
                thermalpts_list.clear();
                thermallist_Adapter.notifyDataSetChanged();
                mSdk3MainBinding.rgbptsTitle.setText("Points on RGB [0]");
                mSdk3MainBinding.thermalptsTitle.setText("Points on Thermal [0]");
                mSdk3MainBinding.myGlSurfaceView.setPerspectiveTransform(rgbpts_list, thermalpts_list);
            }

            if(tId == R.id.button_transform)
            {
                if (rgbpts_list.size() != thermalpts_list.size())
                {
                    Toast.makeText(getApplicationContext(), "Points in RGB cannot 1-to-1 map with Points in Thermal", Toast.LENGTH_LONG).show();
                    return;
                }
                else
                {
                    if (rgbpts_list.size() < 3 || thermalpts_list.size() < 3)
                    {
                        Toast.makeText(getApplicationContext(), "Perspective Transform needs at least 3 pair reference points", Toast.LENGTH_LONG).show();
                    }
                    else
                    {
                        mSdk3MainBinding.myGlSurfaceView.setPerspectiveTransform(rgbpts_list, thermalpts_list);
                    }
                }
            }

            if(tId == R.id.camera_switch)
            {
                if(!mUseFrontCam)
                {
                    mSdk3MainBinding.myGlSurfaceView.setFrontFacing(true);
                    mSdk3MainBinding.myGlSurfaceView.setCameraIndex(CameraBridgeViewBase.CAMERA_ID_FRONT);
                }
                else
                {
                    mSdk3MainBinding.myGlSurfaceView.setFrontFacing(false);
                    mSdk3MainBinding.myGlSurfaceView.setCameraIndex(CameraBridgeViewBase.CAMERA_ID_BACK);
                }
            }
        }
    }


    private class Sdk3TouchListener implements View.OnTouchListener
    {

        @Override
        public boolean onTouch(View view, MotionEvent motionEvent)
        {
            final int tId = view.getId();
            if (tId ==  R.id.my_gl_surface_view)
            {
                if (motionEvent.getAction() == MotionEvent.ACTION_DOWN)
                {
                    if (isTakePts)
                    {
                        rgbpts_list.add(new Point((int) motionEvent.getX(), (int) motionEvent.getY()));
                        rgblist_Adapter.notifyDataSetChanged();
                        mSdk3MainBinding.rgbptsTitle.setText("Points on RGB [" + rgbpts_list.size() + "]");
                    }
                }
            }// End if

            if(tId == R.id.imageView_Thermal)
            {
                if (motionEvent.getAction() == MotionEvent.ACTION_DOWN)
                {
                    if(isTakePts)
                    {
                        thermalpts_list.add(new Point((int)motionEvent.getX() , (int)motionEvent.getY()));
                        thermallist_Adapter.notifyDataSetChanged();
                        mSdk3MainBinding.thermalptsTitle.setText("Points on Thermal [" + thermalpts_list.size() + "]");}// End if
                    }// End if
            }// End if

            return false;
        }
    }// End Sdk3TouchListener

}
