package org.kne.cloud.network;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 修复的BufferedChannel，解决Socket关闭时的数据一致性问题
 */
public class BufferedChannel implements ReadableByteChannel, WritableByteChannel, ScatteringByteChannel, GatheringByteChannel {
    private final ReadableByteChannel inputChannel;
    private final WritableByteChannel outputChannel;
    private final ByteBuffer readBuffer;
    private final ByteBuffer writeBuffer;
    
    
   // private final AtomicBoolean closed = new AtomicBoolean(false);
    private final AtomicBoolean inputShutdown = new AtomicBoolean(false);
    private final AtomicBoolean outputShutdown = new AtomicBoolean(false);

    public BufferedChannel(ReadableByteChannel channel, int bufferSize) {
        this(channel, null, bufferSize);
    }
    
    public BufferedChannel(WritableByteChannel channel, int bufferSize) {
        this(null, channel, bufferSize);
    }
    
    public BufferedChannel(ReadableByteChannel inputChannel, WritableByteChannel outputChannel, int bufferSize) {
        this.inputChannel = inputChannel;
        this.outputChannel = outputChannel;
        this.readBuffer = ByteBuffer.allocateDirect(bufferSize);
        this.writeBuffer = ByteBuffer.allocateDirect(bufferSize);
        
        // 更安全的初始化
        this.readBuffer.limit(0); // 明确设置为空
        this.writeBuffer.clear();
    }

    @Override
    public int read(ByteBuffer dst) throws IOException {
        if ( inputShutdown.get()) {
            throw new ClosedChannelException();
        }
        
       
            // 检查底层通道是否仍然打开
            if (inputChannel != null && !inputChannel.isOpen()) {
                inputShutdown.set(true);
                return handleInputShutdown();
            }
            
            int totalRead = 0;
            boolean eofEncountered = false;
            
            while (dst.hasRemaining() && !eofEncountered) {
                // 如果读缓冲区有数据，先从中读取
                if (readBuffer.hasRemaining()) {
                    int bytesToCopy = Math.min(readBuffer.remaining(), dst.remaining());
                    
                    // 使用绝对位置操作，避免修改缓冲区状态
                    int oldlimit=readBuffer.limit();
                    readBuffer.limit(readBuffer.position()+bytesToCopy);
                        dst.put(readBuffer);
                        readBuffer.limit(oldlimit);
                    
                    totalRead += bytesToCopy;
                    continue;
                }
                
                // 读缓冲区空了，需要重新填充
                readBuffer.clear();
                int bytesRead;
                try {
                    bytesRead = inputChannel.read(readBuffer);
                } catch (IOException e) {
                    // 读取时发生IO异常，标记为关闭
                    inputShutdown.set(true);
                    throw e;
                }
                
                if (bytesRead == -1) {
                    // 到达EOF
                    inputShutdown.set(true);
                    eofEncountered = true;
                } else if (bytesRead == 0) {
                    // 没有数据可用，可能是非阻塞模式
                    break;
                } else {
                    readBuffer.flip();
                }
            }
            
            // 如果遇到EOF且没有读取到任何数据，返回-1
            if (eofEncountered && totalRead == 0) {
                return -1;
            }
            
            return totalRead;
         
    }

    /**
     * 处理输入关闭的情况
     */
    private int handleInputShutdown() throws IOException {
        // 如果读缓冲区还有剩余数据，先返回这些数据
        if (readBuffer.hasRemaining()) {
            return readBuffer.remaining();
        }
        return -1;
    }

    @Override
    public long read(ByteBuffer[] dsts) throws IOException {
        return read(dsts, 0, dsts.length);
    }

    @Override
    public long read(ByteBuffer[] dsts, int offset, int length) throws IOException {
       
        
        long totalRead = 0;
        for (int i = offset; i < offset + length; i++) {
            ByteBuffer dst = dsts[i];
            if (dst == null) {
                throw new NullPointerException("Destination buffer is null");
            }
            
            int bytesRead = read(dst);
            if (bytesRead == -1) {
                // 只有在没有读取任何数据时才返回-1
                return totalRead > 0 ? totalRead : -1;
            }
            totalRead += bytesRead;
        }
        
        return totalRead;
    }

    @Override
    public int write(ByteBuffer src) throws IOException {
       
        
      
            // 检查底层通道是否仍然打开
            if (outputChannel != null && !outputChannel.isOpen()) {
                outputShutdown.set(true);
                throw new ClosedChannelException();
            }
            
            int totalWritten = 0;
            
            while (src.hasRemaining()) {
                // 如果写缓冲区有空间，先填充
                if (writeBuffer.hasRemaining()) {
                    int bytesToCopy = Math.min(writeBuffer.remaining(), src.remaining());
                   int oldlimit= src.limit();
                   src.limit(src.position()+bytesToCopy);
                        writeBuffer.put(src);
                        src.limit(oldlimit);
                    
                    totalWritten += bytesToCopy;
                }
                
                // 如果写缓冲区满了或者源数据还很多，刷新缓冲区
                if (!writeBuffer.hasRemaining() ) {
                    try {
                        flushInternal();
                    } catch (IOException e) {
                        outputShutdown.set(true);
                        throw e;
                    }
                }
            }
            return totalWritten;
            
       
    }

    @Override
    public long write(ByteBuffer[] srcs) throws IOException {
        return write(srcs, 0, srcs.length);
    }

    @Override
    public long write(ByteBuffer[] srcs, int offset, int length) throws IOException {
       
        
        long totalWritten = 0;
        for (int i = offset; i < offset + length; i++) {
            ByteBuffer src = srcs[i];
            if (src == null) {
                throw new NullPointerException("Source buffer is null");
            }
            
            int bytesWritten = write(src);
            totalWritten += bytesWritten;
        }
        
        return totalWritten;
    }

    /**
     * 安全的刷新方法
     */
    public void flush() throws IOException {
        
        
        if (outputChannel == null || outputShutdown.get()) {
            return;
        }
        
        try {
            flushInternal();
        } catch (IOException e) {
            outputShutdown.set(true);
            throw e;
        } 
    }

    /**
     * 内部刷新方法，假设已经持有writeLock
     */
    private void flushInternal() throws IOException {
        if (writeBuffer.position() > 0) {
            writeBuffer.flip();
            
            try {
                while (writeBuffer.hasRemaining()) {
                    int written = outputChannel.write(writeBuffer);
                   // System.out.println("发送"+written);
                    if (written == 0) {
                        // 可能遇到阻塞或关闭
                        if (!outputChannel.isOpen()) {
                            outputShutdown.set(true);
                            throw new ClosedChannelException();
                        }
                        // 给其他操作机会
                        Thread.yield();
                    }
                }
            } finally {
                // 无论发生什么，确保写缓冲区处于可写状态
                writeBuffer.clear();
            }
        }
    }

    /**
     * 安全的关闭方法
     */
    @Override
    public void close() throws IOException {
        
        
        IOException exception = null;
        
        // 先刷新输出缓冲区
        if (outputChannel != null && !outputShutdown.get()) {
         
                if (writeBuffer.position() > 0) {
                    try {
                        flushInternal();
                    } catch (IOException e) {
                        exception = e;
                    }
                }
         
        }
        
        // 关闭底层通道
        try {
            if (inputChannel != null) {
                inputChannel.close();
            }
        } catch (IOException e) {
            if (exception == null) {
                exception = e;
            } else {
                exception.addSuppressed(e);
            }
        }
        
        try {
            if (outputChannel != null) {
                outputChannel.close();
            }
        } catch (IOException e) {
            if (exception == null) {
                exception = e;
            } else {
                exception.addSuppressed(e);
            }
        }
        
        // 清理缓冲区状态
      
            readBuffer.clear();
            readBuffer.limit(0); // 标记为已清空
        
        
        
            writeBuffer.clear();
       
        
        // 设置关闭状态
        inputShutdown.set(true);
        outputShutdown.set(true);
        
        if (exception != null) {
            throw exception;
        }
    }

    /**
     * 优雅关闭 - 只关闭输入或输出
     */
    public void shutdownInput() throws IOException {
        inputShutdown.set(true);
        
            readBuffer.clear();
            readBuffer.limit(0);
        
        
        if (inputChannel instanceof SocketChannel) {
            ((SocketChannel) inputChannel).shutdownInput();
        }
    }
    
    public void shutdownOutput() throws IOException {
        outputShutdown.set(true);
        
            if (writeBuffer.position() > 0) {
                flushInternal();
            }
       
        
        if (outputChannel instanceof SocketChannel) {
            ((SocketChannel) outputChannel).shutdownOutput();
        }
    }

    @Override
    public boolean isOpen() {
        return 
               (inputChannel == null || inputChannel.isOpen()) && 
               (outputChannel == null || outputChannel.isOpen());
    }

    /**
     * 检查是否还有可读数据（包括缓冲区中的）
     */
    public boolean hasRemaining() throws IOException {
        if ( inputShutdown.get()) {
            return false;
        }
        
        
            return readBuffer.hasRemaining() || 
                   (inputChannel != null && inputChannel.isOpen());
        
    }

    /**
     * 获取缓冲区状态信息（用于调试）
     */
    public String getBufferState() {
        
            return String.format(
                "ReadBuffer[pos=%d, lim=%d, cap=%d], WriteBuffer[pos=%d, lim=%d, cap=%d], " +
                "closed=%b, inputShutdown=%b, outputShutdown=%b",
                readBuffer.position(), readBuffer.limit(), readBuffer.capacity(),
                writeBuffer.position(), writeBuffer.limit(), writeBuffer.capacity(), inputShutdown.get(), outputShutdown.get()
            );
       
    }

    // 其他方法保持不变...
    public int available() throws IOException {
        if ( inputShutdown.get()) {
            return 0;
        }
        
      
            return readBuffer.remaining();
       
    }

    public long skip(long n) throws IOException {
        // 实现保持不变...
        return 0;
    }
}