package com.reactlibrary.vishwamdkyclib.ImageAnalysis;

/*
 * Vishwam Corp CONFIDENTIAL

 * Vishwam Corp 2018
 * All Rights Reserved.

 * NOTICE:  All information contained herein is, and remains
 * the property of Vishwam Corp. The intellectual and technical concepts contained
 * herein are proprietary to Vishwam Corp
 * and are protected by trade secret or copyright law of U.S.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Vishwam Corp
 */

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.util.Log;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
/**
 * This class used for imageAnalysis using tensorflow lite.
 * **/

public class ImageAnalysis {

    public AssetManager assetManager;
    public Context context;

    public Queue<ImageObject> bitmapQueue = new LinkedList<>();
    public ArrayList<String> resultStringArray = new ArrayList<>();
    public boolean okForTask, firstFrame;
    public static boolean okForAnalysis, readyForAnalysis = false, canAddData = true;
    public int totalNumFrames;
    public Bitmap realImage, fakeImage;

    final String MODEL_PATH = "31012019.tflite";
    final String LABEL_PATH = "31012019.txt";
    final int INPUT_SIZE = 224;

    public static Classifier classifier;
    private Executor executor = Executors.newSingleThreadExecutor();
    /**
     * Constructor to initialise assetmanager and context.
     * **/
    public ImageAnalysis(AssetManager assetManager, Context context) {
        this.assetManager = assetManager;
        this.context = context;
    }
    /**
     * This is a method initialise tensflow classifier with model stored in the assets.
     * **/
    public void initImageAnalysis() {

        executor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    classifier = TensorFlowImageClassifier.create(
                            assetManager,
                            MODEL_PATH,
                            LABEL_PATH,
                            INPUT_SIZE);

                    readyForAnalysis = true;

                    Log.e("initImageAnalysis", "done");

                } catch (final Exception e) {
                    throw new RuntimeException("Error initializing TensorFlow!", e);
                }
            }
        });
    }
    /**
     * This is reset initial values of different variables.
     * **/
    public void setupImageAnalysis(){
        totalNumFrames = 0;
        realImage = null;
        fakeImage = null;
        okForTask = true;
        firstFrame = true;
        okForAnalysis = true;
        canAddData = true;
        resultStringArray.clear();
    }

    public void startImageAnalysis(){

        new MyAsyncTask().execute();
    }
    /**
     * Method to start image analysis using async task and passing each image object in bitmapQueue obtain on camera frames.
     * Each ImageObject object is compress to create bitmap with byte array as parameter and then scaled down to 224*224 and then processed on tensorflow classifier.
     * **/
    @SuppressLint("StaticFieldLeak")
    class MyAsyncTask extends android.os.AsyncTask<String, String, String> {

        @Override
        protected String doInBackground(String... strings) {

            Iterator<ImageObject> iterator = bitmapQueue.iterator();

            while (iterator.hasNext()){

                if (okForAnalysis) {

                    ImageObject currentImageObject = bitmapQueue.remove();
                    ByteArrayOutputStream out = new ByteArrayOutputStream();

                    YuvImage image = new YuvImage(currentImageObject.byteArray, currentImageObject.parameters.getPreviewFormat(),
                            currentImageObject.previewW, currentImageObject.previewH, null);
                    int quality = 100;   // adjust this as needed

                    image.compressToJpeg(new Rect(0, 0, currentImageObject.previewW, currentImageObject.previewH), quality, out);
                    byte[] finalByte = out.toByteArray();
                    Bitmap finalBitmap = BitmapFactory.decodeByteArray(finalByte, 0, finalByte.length);

                    Bitmap bitmap1 = Bitmap.createScaledBitmap(finalBitmap, 224, 224, false);

                    Matrix matrix = new Matrix();
                    matrix.postRotate(currentImageObject.angle);
                    Bitmap rotated = Bitmap.createBitmap(bitmap1,0,0,bitmap1.getWidth(),bitmap1.getHeight(),matrix,true);

//                    long start = System.currentTimeMillis();
                    final List<Classifier.Recognition> results = classifier.recognizeImage(rotated);
//                    long stop = System.currentTimeMillis();
//                    Log.e("vishwamSukshiTimeFace", String.valueOf(stop-start));
                    if (firstFrame){
                        firstFrame = false;
                    }else {

                        String resultsString = results.toString().replace(" ", "");
                        if (canAddData){
                            resultStringArray.add(resultsString);
                        }
                        totalNumFrames++;
                    }
                }  else {
                    bitmapQueue.clear();
                }
            }
            return null;
        }
    }
    /**
     * Returns image analysis results.
     * **/
    public String getImageIndex(){

        if (totalNumFrames != 0){
            String result = resultStringArray.toString().replaceAll(" ", "");
            return result;
        }else{
            return "";
        }
    }
}