// 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;
/*
 * Copyright (C) 2014 Qiujuer <qiujuer@live.cn>
 * WebSite http://www.qiujuer.net
 * Created 04/16/2015
 * Changed 04/26/2015
 * Version 1.0.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.qiujuer.blink.async;



/**
 * Provides for performing send dispatch from a queue of BinkConn {@link BlinkClient}.
 */
public class AsyncSendDispatcher extends AsyncDispatcher implements SendDispatcher {
    // The queue of send entity.
    private final Queue<SendPacket> mQueue;
    // The sender interface for processing sender requests.
    private Sender mSender;
    // Posting send responses.
    private SendDelivery mDelivery;
    // Used for telling us to die.
    private final AtomicBoolean mSending = new AtomicBoolean(false);
    // Formatter packet to args buffer
    private PacketFormatter mFormatter;
    // Send packet
    private SendPacket mPacket;


// 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;

/*
 * Copyright (C) 2014 Qiujuer <qiujuer@live.cn>
 * WebSite http://www.qiujuer.net
 * Created 04/16/2015
 * Changed 04/26/2015
 * Version 1.0.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.qiujuer.blink.async;



/**
 * Provides for performing send dispatch from a queue of BinkConn {@link BlinkClient}.
 */
public class AsyncSendDispatcher extends AsyncDispatcher implements SendDispatcher {
    // The queue of send entity.
    private final Queue<SendPacket> mQueue;
    // The sender interface for processing sender requests.
    private Sender mSender;
    // Posting send responses.
    private SendDelivery mDelivery;
    // Used for telling us to die.
    private final AtomicBoolean mSending = new AtomicBoolean(false);
    // Formatter packet to args buffer
    private PacketFormatter mFormatter;
    // Send packet
    private SendPacket mPacket;


    public AsyncSendDispatcher(Sender sender, SendDelivery delivery, PacketFormatter formatter, float progressPrecision) {