package com.qualcomm.qti.snpe.imageclassifiers.thread;

import static com.qualcomm.qti.snpe.imageclassifiers.thread.AiSlicingThread.TOTAL_SLICING_PER_IMAGE;

import static org.bytedeco.javacpp.Loader.getCacheDir;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.Log;

import com.qualcomm.qti.snpe.imageclassifiers.detector.Bbox;
import com.qualcomm.qti.snpe.imageclassifiers.detector.RetinaDetector;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.LinkedBlockingDeque;

public class AISliceMergingThread extends Thread{
    /** class's constance*/
    private static final String LOGTAG = AISliceMergingThread.class.getSimpleName();
    private static final int MAX_QUEUE_SIZE = 20;
    private static final String AI_SLING_THREAD = "AI-merge thread";

    /** class main attribute */
    private ConcurrentMap<Integer, CopyOnWriteArrayList<AIResult>> queueMergingResults;
    private LinkedBlockingDeque<AIResult> queueResults;
    private Context mContext;

    public AISliceMergingThread(Context mContext) {
        this.queueResults = new LinkedBlockingDeque<>(MAX_QUEUE_SIZE);
        this.queueMergingResults = new ConcurrentHashMap<>();
        this.mContext = mContext;
    }

    @Override
    public void run() {


        while (true) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            if (queueResults.size() > 0) {
                try {
                    AIResult aiResult = queueResults.takeFirst();
                    int frameId = aiResult.getFrameId();
                    if (!queueMergingResults.containsKey(aiResult.getFrameId())) {
                        queueMergingResults.put(frameId, new CopyOnWriteArrayList<AIResult>());
                    }

                    queueMergingResults.get(frameId).add(aiResult);

                    Log.d(LOGTAG, "map size = " + queueMergingResults);
                    if (queueMergingResults.get(frameId).size() == TOTAL_SLICING_PER_IMAGE) {

                        CopyOnWriteArrayList<AIResult> combinedResults = queueMergingResults.get(frameId);
                        CopyOnWriteArrayList<Bbox> mergedBBoxes = new CopyOnWriteArrayList<Bbox>();

                        queueMergingResults.remove(frameId);

                        /** DO AI-MERGING-RESULTS WITH combinedResults */
//                        Bitmap originalImage = aiResult.getOriginalBitmap();
//                        final Bitmap bmpcopy = originalImage.copy(Bitmap.Config.ARGB_8888, true);
//                        Canvas canvas = new Canvas(bmpcopy);
//
//                        Paint paint = new Paint();
//                        //paint.setAlpha(0xA0); // the transparency
//                        paint.setColor(Color.RED); // color is red
//                        paint.setStyle(Paint.Style.STROKE); // stroke or fill or ...
//                        paint.setStrokeWidth(1); // the stroke width
//                        for (AIResult aiResult_ : combinedResults) {
//                            for (Bbox box0 : aiResult_.getListBox()) {
//                                mergedBBoxes.add(box0);
////                            Log.d(LOGTAG + "singleBoxInfo", "co-ord= " + box0.x1 + " " + box0.x2 +" " + box0.y1 + " " + box0.y2 + " | conf = " + box0.conf);
//                                Rect r = new Rect((int) box0.x1, (int) box0.y1, (int) box0.x2, (int) box0.y2);
//
//                                canvas.drawRect(r, paint);
//                            }
//                        }
//
//                        Log.d(LOGTAG + "combine", "saving combined image");
//                        String filename = System.currentTimeMillis() + "_" + frameId + "_combined";
//                        savebitmap(bmpcopy, filename);

//                        Bitmap originalImage_ = aiResult.getOriginalBitmap();
//                        final Bitmap bmpcopy_ = originalImage_.copy(Bitmap.Config.ARGB_8888, true);
//                        Canvas canvas_ = new Canvas(bmpcopy_);
//
//                        Paint paint_ = new Paint();
//                        //paint.setAlpha(0xA0); // the transparency
//                        paint_.setColor(Color.RED); // color is red
//                        paint_.setStyle(Paint.Style.STROKE); // stroke or fill or ...
//                        paint_.setStrokeWidth(1); // the stroke width

//                        for (Bbox mBox : mergedBBoxes) {
//
////                            Log.d(LOGTAG + "singleBoxInfo", "co-ord= " + box0.x1 + " " + box0.x2 +" " + box0.y1 + " " + box0.y2 + " | conf = " + box0.conf);
//                            Rect r = new Rect((int) mBox.x1, (int) mBox.y1, (int) mBox.x2, (int) mBox.y2);
//                            canvas_.drawRect(r, paint_);
//                        }
//
//                        Log.d(LOGTAG + "merging", "saving merged image");
//                        String filename_ = System.currentTimeMillis() + "_" + frameId + "_merged";
//                        savebitmap(bmpcopy_, filename_);

                        UnionMergeProcess UnionMerge = new UnionMergeProcess((float)0.7,"IOS",true,mergedBBoxes);
                        CopyOnWriteArrayList<Bbox> UnionMergedBBoxes = UnionMerge.UnionMerging();

                        Bitmap originalImageMerge = aiResult.getOriginalBitmap();
                        final Bitmap bmpcopyMerge = originalImageMerge.copy(Bitmap.Config.ARGB_8888, true);
                        Canvas canvasMerge = new Canvas(bmpcopyMerge);

                        Paint paintMerge = new Paint();
                        //paint.setAlpha(0xA0); // the transparency
                        paintMerge.setColor(Color.RED); // color is red
                        paintMerge.setStyle(Paint.Style.STROKE); // stroke or fill or ...
                        paintMerge.setStrokeWidth(1); // the stroke width

                        for (Bbox mBox : UnionMergedBBoxes) {

//                            Log.d(LOGTAG + "singleBoxInfo", "co-ord= " + box0.x1 + " " + box0.x2 +" " + box0.y1 + " " + box0.y2 + " | conf = " + box0.conf);
                            Rect r = new Rect((int) mBox.x1, (int) mBox.y1, (int) mBox.x2, (int) mBox.y2);
                            canvasMerge.drawRect(r, paintMerge);
                        }

                        Log.d(LOGTAG + "Union merging", "saving Union merged image");
                        String filenameMerge = System.currentTimeMillis() + "_" + frameId + "_Unionmerged";
                        savebitmap(bmpcopyMerge, filenameMerge);


                    }

                } catch (InterruptedException | IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    public boolean addItem(AIResult aiResult) {
        if (queueResults.size() > MAX_QUEUE_SIZE){
            try {
                queueResults.takeFirst();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }


        return queueResults.offerLast(aiResult);
    }

    public File savebitmap(Bitmap bmp, String filename) throws IOException {
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        bmp.compress(Bitmap.CompressFormat.JPEG, 60, bytes);
        File f = new File(mContext.getCacheDir()
                + File.separator + filename +".jpg");
        Log.d(LOGTAG + "fpath", "file-path= " + (getCacheDir()
                + File.separator + filename +".jpg"));
        f.createNewFile();
        FileOutputStream fo = new FileOutputStream(f);
        fo.write(bytes.toByteArray());
        fo.close();
        return f;
    }
}
