package com.izouma.screen_stream_plugin;

import android.content.Context;
import android.graphics.Bitmap;
import android.media.Image;
import android.media.ImageReader;
import android.util.Log;

import org.bytedeco.javacpp.avcodec;
import org.bytedeco.javacv.AndroidFrameConverter;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameRecorder;

import java.io.File;
import java.nio.ByteBuffer;
import java.util.Map;

public class ImageAvailableListener implements ImageReader.OnImageAvailableListener {
    private static final String TAG = "ImageAvailableListener";

    private AndroidFrameConverter frameConverter;
    private FFmpegFrameRecorder   frameRecorder;
    private long                  frameCount;
    private OnMatchedListener     onMatchedListener;
    private String                videoPath;

    public String getVideoPath() {
        return videoPath;
    }

    public ImageAvailableListener(Context context) {
        frameConverter = new AndroidFrameConverter();
        File recordFile = new File(context.getExternalFilesDir("record"), "record" + System.currentTimeMillis() + ".mp4");
        videoPath = recordFile.getAbsolutePath();
        frameRecorder = new FFmpegFrameRecorder(recordFile, 1280, 720, 1);
        frameRecorder.setVideoBitrate(3 * 1024 * 1024);
        frameRecorder.setFrameRate(24);
        frameRecorder.setVideoOption("preset", "ultrafast");
        frameRecorder.setVideoOption("crf", "28");
        frameRecorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
        frameRecorder.setFormat("mp4");
        try {
            frameRecorder.start();
        } catch (FrameRecorder.Exception e) {
            e.printStackTrace();
        }
    }

    public void setOnMatchedListener(OnMatchedListener onMatchedListener) {
        this.onMatchedListener = onMatchedListener;
    }

    public void release() {
        try {
            frameRecorder.stop();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            frameRecorder = null;
        }
    }

    @Override
    public void onImageAvailable(ImageReader reader) {
        if (frameRecorder == null) {
            return;
        }
        frameCount++;
        try (Image image = reader.acquireLatestImage()) {
            if (image != null) {
                Image.Plane[] planes = image.getPlanes();
                ByteBuffer buffer = planes[0].getBuffer();

                Bitmap bitmap = Bitmap.createBitmap(1280, 720, Bitmap.Config.ARGB_8888);
                bitmap.copyPixelsFromBuffer(buffer);
                if (frameCount % 3 != 0) {
                    bitmap.recycle();
                    return;
                }
                if (onMatchedListener != null) {
                    onMatchedListener.onProgress();
                }
                Frame vFrame = frameConverter.convert(bitmap);
                try {
                    frameRecorder.record(vFrame);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                bitmap.recycle();
                Log.d(TAG, "record " + frameCount + " frame");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public interface OnMatchedListener {
        void onProgress();

        void onMatched(Map<String, String> result);
    }
}
