package org.kne.codec.kif;
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * 多模式并行编码的 Future 包装器
 * 等待所有子任务完成，选择体积最小的结果
 */
public class MultiModeFuture implements Future<KIFCompressedImageBlock> {
    
    private final ArrayList<Future<KIFCompressedImageBlock>> futures;
    private volatile KIFCompressedImageBlock bestResult;
    private volatile boolean done = false;
    private volatile boolean cancelled = false;
    private final Object lock = new Object();
    
    public MultiModeFuture(ArrayList< Future<KIFCompressedImageBlock>> futures) {
        if (futures == null || futures.size() == 0) {
            throw new IllegalArgumentException("至少需要1个子任务");
        }
        this.futures = futures;
    }
    
    @Override
    public boolean cancel(boolean mayInterruptIfRunning) {
        if (isDone()) {
            return false;
        }
        cancelled = true;
        boolean allCancelled = true;
        for (Future<KIFCompressedImageBlock> f : futures) {
            if (!f.cancel(mayInterruptIfRunning)) {
                allCancelled = false;
            }
        }
        return allCancelled;
    }
    
    @Override
    public boolean isCancelled() {
        return cancelled;
    }
    
    @Override
    public boolean isDone() {
        // 如果已经标记完成，直接返回 true
        if (done) {
            return true;
        }
        
        // 检查是否所有子任务都已完成
        boolean allDone = true;
        for (Future<KIFCompressedImageBlock> f : futures) {
            if (!f.isDone()) {
                allDone = false;
                break;
            }
        }
        
        if (allDone) {
            // 所有子任务完成，自动合并结果（不阻塞）
            synchronized (lock) {
                if (!done) {
                    // 如果之前没有合并过，现在合并
                    KIFCompressedImageBlock minBlock = null;
                    Exception lastException = null;
                    
                    for (Future<KIFCompressedImageBlock> f : futures) {
                        try {
                            KIFCompressedImageBlock block = f.get(); // 此时不会阻塞，因为 isDone() 已为 true
                            if (block != null) {
                                if (minBlock == null || block.compareTo(minBlock) < 0) {
                                    minBlock = block;
                                }
                            }
                        } catch (Exception e) {
                            lastException = e;
                        }
                    }
                    
                    if (minBlock != null||(lastException!=null)) {
                        bestResult = minBlock;
                        done = true;
                    }
                }
            }
        }
        
        return done;
    }
    
    @Override
    public KIFCompressedImageBlock get() throws InterruptedException, ExecutionException {
        if (done && bestResult != null) {
            return bestResult;
        }
        
        synchronized (lock) {
            if (done && bestResult != null) {
                return bestResult;
            }
            
            // 等待所有子任务完成
            Exception lastException = null;
            KIFCompressedImageBlock minBlock = null;
            
            for (Future<KIFCompressedImageBlock> f : futures) {
                try {
                    KIFCompressedImageBlock block = f.get();
                    if (block != null) {
                        if (minBlock == null || block.compareTo(minBlock) < 0) {
                            minBlock = block;
                        }
                    }
                } catch (ExecutionException e) {
                    lastException = e;
                    // 继续收集其他任务的结果
                }
            }
            
            // 如果有至少一个成功的结果，返回最小的
            if (minBlock != null) {
                bestResult = minBlock;
                done = true;
                return bestResult;
            }
            
            // 全部失败，抛出最后一个异常
            if (lastException != null) {
                throw new ExecutionException(lastException);
            }
            
            // 理论上不会走到这里
            throw new ExecutionException(new IllegalStateException("所有子任务返回了 null"));
        }
    }
    
    @Override
    public KIFCompressedImageBlock get(long timeout, TimeUnit unit) 
            throws InterruptedException, ExecutionException, TimeoutException {
        if (done && bestResult != null) {
            return bestResult;
        }
        
        synchronized (lock) {
            if (done && bestResult != null) {
                return bestResult;
            }
            
            long deadline = System.nanoTime() + unit.toNanos(timeout);
            Exception lastException = null;
            KIFCompressedImageBlock minBlock = null;
            
            for (Future<KIFCompressedImageBlock> f : futures) {
                long remaining = deadline - System.nanoTime();
                if (remaining <= 0) {
                    throw new TimeoutException("等待超时");
                }
                
                try {
                    KIFCompressedImageBlock block = f.get(remaining, TimeUnit.NANOSECONDS);
                    if (block != null) {
                        if (minBlock == null || block.compareTo(minBlock) < 0) {
                            minBlock = block;
                        }
                    }
                } catch (ExecutionException e) {
                    lastException = e;
                }
            }
            
            if (minBlock != null) {
                bestResult = minBlock;
                done = true;
                return bestResult;
            }
            
            if (lastException != null) {
                throw new ExecutionException(lastException);
            }
            
            throw new ExecutionException(new IllegalStateException("所有子任务返回了 null"));
        }
    }
   /* @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("MultiModeFuture{\n");
        
        // 获取各个子任务的模式（如果能取到的话）
        // 由于 Future 可能还没完成，我们只能尽量获取已完成的信息
        sb.append("  子任务数: ").append(futures.length).append("\n");
        
        // 尝试获取每个子任务的结果（如果已完成）
        for (int i = 0; i < futures.length; i++) {
            Future<KIFCompressedImageBlock> f = futures[i];
            if (f.isDone()) {
                try {
                    // 如果已经完成，可以安全获取
                    KIFCompressedImageBlock block = f.get();
                    if (block != null) {
                        sb.append(String.format("  模式 %d: size=%d bytes, 压缩率=%.2f%%\n",
                            block.getPredictMode() & 0xFF,
                            block.getData().length,
                            (double) block.getData().length / block.getSizeBeforeCompress() * 100
                        ));
                    } else {
                        sb.append("  模式 ").append(i).append(": null\n");
                    }
                } catch (Exception e) {
                    sb.append("  模式 ").append(i).append(": 获取失败 (").append(e.getMessage()).append(")\n");
                }
            } else {
                // 如果还没完成，尝试获取模式（需要额外传递模式信息）
                // 这里无法直接从 Future 中提取模式，因为 Future 只存结果
                // 可以在调用时传入模式编号或使用自定义 Future 子类携带模式信息
                sb.append("  子任务 ").append(i).append(": 未完成\n");
            }
        }
        
        // 如果有最终结果，显示
        if (done && bestResult != null) {
            sb.append("  最终选择:\n");
            sb.append(String.format("    模式: %d\n", bestResult.getPredictMode() & 0xFF));
            sb.append(String.format("    体积: %d bytes\n", bestResult.getData().length));
            sb.append(String.format("    压缩率: %.2f%%\n", 
                (double) bestResult.getData().length / bestResult.getSizeBeforeCompress() * 100
            ));
            sb.append("    宽x高: ").append(bestResult.getWidth()).append("x").append(bestResult.getHeight());
        } else if (done && bestResult == null) {
            sb.append("  最终结果: null (所有子任务失败)\n");
        } else {
            sb.append("  状态: 未完成，仍在等待子任务...\n");
        }
        
        sb.append("}");
        return sb.toString();
    }*/
    @Override
    public String toString() {
    	return  bestResult.toString();
    }
   
}