// Path: Java/Blink/library/src/net/qiujuer/blink/BlinkClient.java
// public class BlinkClient extends BlinkConnect {
//     private SocketAddress mAddress;
// 
//     public BlinkClient() {
//         setDelivery(new ExecutorDelivery(null));
//     }
// 
//     public boolean connect(String ip, int port) {
//         return connect(new InetSocketAddress(ip, port));
//     }
// 
//     public boolean connect(InetSocketAddress address) {
//         return connect((SocketAddress) address);
//     }
// 
//     public boolean connect(SocketAddress address) {
//         mAddress = address;
//         try {
//             SocketChannel channel = SocketChannel.open(mAddress);
//             boolean connected = channel.isConnected();
//             if (connected) {
//                 channel.configureBlocking(false);
//                 start(channel);
//             }
//             return connected;
//         } catch (IOException e) {
//             e.printStackTrace();
//             return false;
//         }
//     }
// 
//     public boolean reconnect() {
//         if (mAddress == null)
//             throw new NullPointerException("SocketChannel address is null, you should call connect.");
// 
//         dispose();
// 
//         return connect(mAddress);
//     }
// }
// 
// Path: Java/Blink/library/src/net/qiujuer/blink/core/PacketFormatter.java
// public abstract class PacketFormatter extends PacketFilter {
//     protected SendPacket mPacket;
// 
//     public abstract float format();
// 
//     public void setPacket(SendPacket packet) {
//         mPacket = packet;
//     }
// 
// }
// 
// Path: Android/Blink/library/src/main/java/net/qiujuer/blink/core/SendPacket.java
// public abstract class SendPacket extends BlinkPacket {
//     private final SendListener mListener;
//     private boolean mCanceled;
//     private BlinkConn mBlinkConn;
// 
// 
//     public SendPacket(byte type, SendListener listener) {
//         super(type);
//         mListener = listener;
//     }
// 
//     public SendListener getListener() {
//         return mListener;
//     }
// 
//     /**
//      * Cancel the packet to send
//      * If the packet on sending you can't cancel it
//      * But you can cancel sending notify callback
//      */
//     public void cancel() {
//         mCanceled = true;
//         if (mBlinkConn != null) {
//             mBlinkConn.cancel(this);
//             mBlinkConn = null;
//         }
//     }
// 
//     /**
//      * Get the packet iscanceled
//      *
//      * @return Is Canceled
//      */
//     public boolean isCanceled() {
//         return mCanceled;
//     }
// 
//     /**
//      * Set The BlinkConn to Cancel from queue
//      *
//      * @param blinkConn BlinkConn
//      * @return SendPacket
//      */
//     SendPacket setBlinkConn(BlinkConn blinkConn) {
//         mBlinkConn = blinkConn;
//         return this;
//     }
// 
//     /**
//      * On Sender send the packet call this to send packet info
//      * The bytes in 0~32767 size
//      *
//      * @param buffer Send buffer
//      * @param index  Buffer start index
//      * @return Read to buffer count
//      */
//     public short readInfo(byte[] buffer, int index) {
//         return 0;
//     }
// 
//     /**
//      * Sender read same data to send
//      *
//      * @param buffer Buffer
//      * @param offset Buffer offset
//      * @param count  Buffer count
//      * @return Read to buffer count
//      */
//     public abstract int read(byte[] buffer, int offset, int count);
// }
// 
// Path: Java/Blink/library/src/net/qiujuer/blink/core/Sender.java
// public interface Sender extends Disposable {
//     /**
//      * Get socket send buffer size
//      *
//      * @return Buffer Size
//      */
//     int getSendBufferSize();
// 
//     /**
//      * Async send same byte
//      *
//      * @param e SocketAsyncEventArgs
//      * @return Status
//      */
//     boolean sendAsync(IoEventArgs e);
// }


import net.qiujuer.blink.BlinkClient;
import net.qiujuer.blink.core.PacketFilter;
import net.qiujuer.blink.core.PacketFormatter;
import net.qiujuer.blink.core.SendDispatcher;
import net.qiujuer.blink.core.SendPacket;
import net.qiujuer.blink.core.Sender;
import net.qiujuer.blink.core.delivery.SendDelivery;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;
            thread.start();
        }
    }

    /**
     * Delete a packet from queue to cancel
     *
     * @param packet SendPacket
     */
    @Override
    public void cancel(SendPacket packet) {
        synchronized (mQueue) {
            mQueue.remove(packet);
        }
    }

    /**
     * Notify send progress
     */
    private void notifyProgress(float progress) {
        SendDelivery delivery = mDelivery;
        SendPacket packet = mPacket;

        if (!mDisposed.get()
                && delivery != null
                && packet != null
                && isNotifyProgress(progress)) {
            if (progress == PacketFilter.STATUS_START)
                delivery.postSendStart(packet);
            else if (progress == PacketFilter.STATUS_END)
// Path: Java/Blink/library/src/net/qiujuer/blink/BlinkClient.java
// public class BlinkClient extends BlinkConnect {
//     private SocketAddress mAddress;
// 
//     public BlinkClient() {
//         setDelivery(new ExecutorDelivery(null));
//     }
// 
//     public boolean connect(String ip, int port) {
//         return connect(new InetSocketAddress(ip, port));
//     }
// 
//     public boolean connect(InetSocketAddress address) {
//         return connect((SocketAddress) address);
//     }
// 
//     public boolean connect(SocketAddress address) {
//         mAddress = address;
//         try {
//             SocketChannel channel = SocketChannel.open(mAddress);
//             boolean connected = channel.isConnected();
//             if (connected) {
//                 channel.configureBlocking(false);
//                 start(channel);
//             }
//             return connected;
//         } catch (IOException e) {
//             e.printStackTrace();
//             return false;
//         }
//     }
// 
//     public boolean reconnect() {
//         if (mAddress == null)
//             throw new NullPointerException("SocketChannel address is null, you should call connect.");
// 
//         dispose();
// 
//         return connect(mAddress);
//     }
// }
// 
// Path: Java/Blink/library/src/net/qiujuer/blink/core/PacketFormatter.java
// public abstract class PacketFormatter extends PacketFilter {
//     protected SendPacket mPacket;
// 
//     public abstract float format();
// 
//     public void setPacket(SendPacket packet) {
//         mPacket = packet;
//     }
// 
// }
// 
// Path: Android/Blink/library/src/main/java/net/qiujuer/blink/core/SendPacket.java
// public abstract class SendPacket extends BlinkPacket {
//     private final SendListener mListener;
//     private boolean mCanceled;
//     private BlinkConn mBlinkConn;
// 
// 
//     public SendPacket(byte type, SendListener listener) {
//         super(type);
//         mListener = listener;
//     }
// 
//     public SendListener getListener() {
//         return mListener;
//     }
// 
//     /**
//      * Cancel the packet to send
//      * If the packet on sending you can't cancel it
//      * But you can cancel sending notify callback
//      */
//     public void cancel() {
//         mCanceled = true;
//         if (mBlinkConn != null) {
//             mBlinkConn.cancel(this);
//             mBlinkConn = null;
//         }
//     }
// 
//     /**
//      * Get the packet iscanceled
//      *
//      * @return Is Canceled
//      */
//     public boolean isCanceled() {
//         return mCanceled;
//     }
// 
//     /**
//      * Set The BlinkConn to Cancel from queue
//      *
//      * @param blinkConn BlinkConn
//      * @return SendPacket
//      */
//     SendPacket setBlinkConn(BlinkConn blinkConn) {
//         mBlinkConn = blinkConn;
//         return this;
//     }
// 
//     /**
//      * On Sender send the packet call this to send packet info
//      * The bytes in 0~32767 size
//      *
//      * @param buffer Send buffer
//      * @param index  Buffer start index
//      * @return Read to buffer count
//      */
//     public short readInfo(byte[] buffer, int index) {
//         return 0;
//     }
// 
//     /**
//      * Sender read same data to send
//      *
//      * @param buffer Buffer
//      * @param offset Buffer offset
//      * @param count  Buffer count
//      * @return Read to buffer count
//      */
//     public abstract int read(byte[] buffer, int offset, int count);
// }
// 
// Path: Java/Blink/library/src/net/qiujuer/blink/core/Sender.java
// public interface Sender extends Disposable {
//     /**
//      * Get socket send buffer size
//      *
//      * @return Buffer Size
//      */
//     int getSendBufferSize();
// 
//     /**
//      * Async send same byte
//      *
//      * @param e SocketAsyncEventArgs
//      * @return Status
//      */
//     boolean sendAsync(IoEventArgs e);
// }


// Path: Java/Blink/library/src/net/qiujuer/blink/async/AsyncSendDispatcher.java
import net.qiujuer.blink.BlinkClient;
import net.qiujuer.blink.core.PacketFilter;
import net.qiujuer.blink.core.PacketFormatter;
import net.qiujuer.blink.core.SendDispatcher;
import net.qiujuer.blink.core.SendPacket;
import net.qiujuer.blink.core.Sender;
import net.qiujuer.blink.core.delivery.SendDelivery;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;

            thread.start();
        }
    }

    /**
     * Delete a packet from queue to cancel
     *
     * @param packet SendPacket
     */
    @Override
    public void cancel(SendPacket packet) {
        synchronized (mQueue) {
            mQueue.remove(packet);
        }
    }

    /**
     * Notify send progress
     */
    private void notifyProgress(float progress) {
        SendDelivery delivery = mDelivery;
        SendPacket packet = mPacket;

        if (!mDisposed.get()
                && delivery != null
                && packet != null
                && isNotifyProgress(progress)) {
            if (progress == PacketFilter.STATUS_START)
                delivery.postSendStart(packet);
            else if (progress == PacketFilter.STATUS_END)
                delivery.postSendCompleted(packet);