package org.kne.codec.kvf;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;

import javax.imageio.ImageIO;

import org.jcodec.common.model.Picture;
import org.jcodec.scale.AWTUtil;
import org.kne.opencl64.OpenCLDevice;
import org.kne.opencl64.concurrent.OpenCLExecutors;

public class KVFCodec {
	private static ThreadPoolExecutor cpupool ;
	static {
		cpupool= (ThreadPoolExecutor) Executors.newFixedThreadPool(
		    Runtime.getRuntime().availableProcessors(),
		    new ThreadFactory() {
		        private final AtomicInteger threadNumber = new AtomicInteger(1);
		        @Override
		        public Thread newThread(Runnable r) {
		            Thread t = new Thread(r, "KVFCodec-CPU-Worker-" + threadNumber.getAndIncrement());
		            t.setDaemon(true);  // 设置为守护线程
		            return t;
		        }
		    }
		);
	}
	public static Future<byte[]> encodeIFrame(BufferedImage frame,String formattype,Consumer<byte[]>result) {
		cpuBackPressure();
		return cpupool.submit(()->{
			ByteArrayOutputStream boos=new ByteArrayOutputStream();
			ImageIO.write(frame, formattype, boos);
			byte[]resultdata=boos.toByteArray();
			if(result!=null) {
				result.accept(resultdata);
			}
			return resultdata;
		});
	}
	
	public static Future<byte[]> encodeIFrame(Picture picture,String formattype,Consumer<byte[]>result) {
		cpuBackPressure();
		return cpupool.submit(()->{
		    BufferedImage frame = AWTUtil.toBufferedImage(picture);
			ByteArrayOutputStream boos=new ByteArrayOutputStream();
			ImageIO.write(frame, formattype, boos);
			byte[]resultdata=boos.toByteArray();
			if(result!=null) {
				result.accept(resultdata);
			}
			return resultdata;
		});
	}
	
	public static Future<BufferedImage> decodeIFrame(byte[]data,Consumer<BufferedImage>result){
		cpuBackPressure();
		return cpupool.submit(()->{
			ByteArrayInputStream biis=new ByteArrayInputStream(data);
			BufferedImage resultframe= ImageIO.read(biis);
			biis.close();
			if(result!=null) {
				result.accept(resultframe);
			}
			return resultframe;
		});
	}
	
	
	public static void cpuBackPressure() {
		while(isCPUOverloaded()) {
			try {
				Thread.sleep(1);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 判断是否过载（调用方可据此决定是否降级处理）
	 */
	public static boolean isCPUOverloaded() {
	    return cpupool.getQueue().size() > cpupool.getPoolSize() * 2;
	}
}
