package com.jachdev.consumerprotection.util;

import android.content.Context;
import android.media.Image;
import android.net.Uri;
import android.util.Log;
import android.widget.Toast;

import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.mlkit.vision.common.InputImage;
import com.google.mlkit.vision.text.Text;
import com.google.mlkit.vision.text.TextRecognition;
import com.google.mlkit.vision.text.TextRecognizer;
import com.google.mlkit.vision.text.latin.TextRecognizerOptions;
import com.jachdev.consumerprotection.AppConstant;
import com.jachdev.consumerprotection.R;
import com.jachdev.consumerprotection.data.enums.TestReportType;

import java.io.IOException;
import java.util.List;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import androidx.annotation.NonNull;
import androidx.camera.core.ImageAnalysis;
import androidx.camera.core.ImageProxy;

/**
 * Created by Charitha Ratnayake(charitha.r@eyepax.com) on 3/19/2022.
 */
public class ImageAnalyzer {

    private static final String TAG = ImageAnalyzer.class.getSimpleName();
    private Context context;
    private TextRecognizer recognizer;
    private ImageAnalyzerListener listener;

    public ImageAnalyzer(Context context, ImageAnalyzerListener listener) {
        this.context = context;
        this.listener = listener;

        recognizer = TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS);
    }

    public void analyze(Uri uri) {

        if(uri == null){
            Toast.makeText(context, context.getString(R.string.error_please_insert_a_valid_image),
                    Toast.LENGTH_LONG).show();
            return;
        }

        InputImage image = null;
        try {
            image = InputImage.fromFilePath(context, uri);
        } catch (IOException e) {
            e.printStackTrace();
        }

        Task<Text> result =
                recognizer.process(image)
                        .addOnSuccessListener(new OnSuccessListener<Text>() {
                            @Override
                            public void onSuccess(Text visionText) {
                                Log.d(TAG, "onSuccess: " + visionText.getText());

                                extractGlucose(visionText.getTextBlocks());
                                extractCholesterol(visionText.getTextBlocks());
                                extractHdl(visionText.getTextBlocks());
                                extractLdl(visionText.getTextBlocks());
                            }
                        })
                        .addOnFailureListener(
                                new OnFailureListener() {
                                    @Override
                                    public void onFailure(@NonNull Exception e) {
                                        // Task failed with an exception
                                        // ...
                                    }
                                });
    }

    private void extractLdl(List<Text.TextBlock> blocks) {
        String key = "", unit = "";
        double amount = 0;

        for (int x = 0; x < blocks.size(); x++){
            key = blocks.get(x).getText();

            if(key.equalsIgnoreCase(TestReportType.LDL.getName())){
                try{
                    amount = Double.parseDouble(blocks.get(x + 1).getText());
                    unit = blocks.get(x + 2).getText();

                    Log.d(TAG, "extractLdl: key = " + key);
                    Log.d(TAG, "extractLdl: amount = " + amount);

//                    Pattern p = Pattern.compile(AppConstant.ImageExtractor.REG_GLUCOSE);
//                    Matcher m = p.matcher(value);
//
//                    if(m.find()){
//                        MatchResult mr = m.toMatchResult();
//                        amount = Double.parseDouble(mr.group(1));
//                        unit = mr.group(2);
//                    }

                    if(listener != null)
                        listener.onTestReportExtract(TestReportType.LDL, amount, unit);

                    break;
                }catch (Exception ignored){

                }
            }

            if(x == blocks.size() - 1){

                if(listener != null)
                    listener.onTestReportExtract(TestReportType.LDL, 0, null);
            }
        }
    }

    private void extractHdl(List<Text.TextBlock> blocks) {
        String key = "", unit = "";
        double amount = 0;

        for (int x = 0; x < blocks.size(); x++){
            key = blocks.get(x).getText();

            if(key.equalsIgnoreCase(TestReportType.HDL.getName())){
                try{
                    amount = Double.parseDouble(blocks.get(x + 1).getText());
                    unit = blocks.get(x + 2).getText();

                    Log.d(TAG, "extractHdl: key = " + key);
                    Log.d(TAG, "extractHdl: amount = " + amount);

//                    Pattern p = Pattern.compile(AppConstant.ImageExtractor.REG_GLUCOSE);
//                    Matcher m = p.matcher(value);
//
//                    if(m.find()){
//                        MatchResult mr = m.toMatchResult();
//                        amount = Double.parseDouble(mr.group(1));
//                        unit = mr.group(2);
//                    }

                    if(listener != null)
                        listener.onTestReportExtract(TestReportType.HDL, amount, unit);

                    break;
                }catch (Exception ignored){

                }
            }

            if(x == blocks.size() - 1){

                if(listener != null)
                    listener.onTestReportExtract(TestReportType.HDL, 0, null);
            }
        }
    }

    private void extractCholesterol(List<Text.TextBlock> blocks) {
        String key = "", unit = "";
        double amount = 0;

        for (int x = 0; x < blocks.size(); x++){
            key = blocks.get(x).getText();

            if(key.equalsIgnoreCase(TestReportType.CHOLESTEROL.getName())){
                try{
                    amount = Double.parseDouble(blocks.get(x + 3).getText());
                    unit = blocks.get(x + 1).getText();

                    Log.d(TAG, "extractCholesterol: key = " + key);
                    Log.d(TAG, "extractCholesterol: amount = " + amount);

//                    Pattern p = Pattern.compile(AppConstant.ImageExtractor.REG_GLUCOSE);
//                    Matcher m = p.matcher(value);
//
//                    if(m.find()){
//                        MatchResult mr = m.toMatchResult();
//                        amount = Double.parseDouble(mr.group(1));
//                        unit = mr.group(2);
//                    }

                    if(listener != null)
                        listener.onTestReportExtract(TestReportType.CHOLESTEROL, amount, unit);

                    break;
                }catch (Exception ignored){

                }
            }

            if(x == blocks.size() - 1){

                if(listener != null)
                    listener.onTestReportExtract(TestReportType.CHOLESTEROL, 0, null);
            }
        }
    }

    private void extractGlucose(List<Text.TextBlock> blocks) {
        String key = "", value = "", unit = "";
        double amount = 0;

        for (int x = 0; x < blocks.size(); x++){
            key = blocks.get(x).getText();

            if(key.equalsIgnoreCase(TestReportType.GLUCOSE.getName())){
                try{
                    value = blocks.get(x + 1).getText();

                    Log.d(TAG, "extractGlucose: text = " + key);
                    Log.d(TAG, "extractGlucose: level = " + value);

                    Pattern p = Pattern.compile(AppConstant.ImageExtractor.REG_GLUCOSE);
                    Matcher m = p.matcher(value);

                    if(m.find()){
                        MatchResult mr = m.toMatchResult();
                        amount = Double.parseDouble(mr.group(1));
                        unit = mr.group(2);
                    }

                    if(listener != null)
                        listener.onTestReportExtract(TestReportType.GLUCOSE, amount, unit);

                    break;
                }catch (Exception ignored){

                }
            }

            if(x == blocks.size() - 1){

                if(listener != null)
                    listener.onTestReportExtract(TestReportType.GLUCOSE, 0, null);
            }
        }
    }

    public interface ImageAnalyzerListener{
        void onTestReportExtract(TestReportType type, double amount, String unit);
    }
}