package org.kne.cloud.network.srv6;

import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;

import org.kne.cloud.network.ipv6.IPv6Packet;

public class TCPTransimitAgent {
	public TCPTransimitAgent() {
	}
	private ReentrantLock rlock=new ReentrantLock();
	private Map<Long,TcpPacketEntry> tcps=new ConcurrentHashMap();
	public Map<Long,TcpPacketEntry> getTcps() {
		return tcps;
	}
	public static class TcpPacketEntry{
		private IPv6Packet packet;
		private  long sequenceNumber;
		private  int length;
		private long addtime=System.nanoTime();
		
		public TcpPacketEntry(IPv6Packet packet, long sequenceNumber, int length) {
			super();
			this.packet = packet;
			this.sequenceNumber = sequenceNumber;
			this.length = length;
		}
		public IPv6Packet getPacket() {
			return packet;
		}
		public long getAddtime() {
			return addtime;
		}
		public boolean checkTimeOut() {
			return System.nanoTime()-addtime>1000000000L;
		}
		public long getSequenceNumber() {
			return sequenceNumber;
		}
		public int getLength() {
			return length;
		}
		@Override
		public String toString() {
			return "TcpPacketEntry [sequenceNumber=" + sequenceNumber + ", length=" + length
					+ ", addtime=" + addtime + "]";
		}
	}
	public boolean sortPackets(IPv6Packet pack,long seq,int length, IPv6PacketConsumer packconsumer) throws IOException {
		if(length<=0) {
			packconsumer.accept(pack);
			return true;
		}
		rlock.lock();
		try {
			//System.out.println("包序号："+seq+" 长度："+length);
			Set<Entry<Long,TcpPacketEntry >>et= tcps.entrySet();
			for (Iterator<Entry<Long, TcpPacketEntry>> iterator = et.iterator(); iterator.hasNext();) {
				Entry<Long, TcpPacketEntry> entry = (Entry<Long, TcpPacketEntry>) iterator.next();
				if(entry.getValue().checkTimeOut()) {
					iterator.remove();
				}
			}
			TcpPacketEntry tpe= tcps.get(seq);
			if(tpe==null) {
				tcps.put(seq, new TcpPacketEntry(pack, seq, length));
				packconsumer.accept(pack);
			}else {
			if(tpe.getLength()==length) {
				return false;
			}else {
				tcps.put(seq, new TcpPacketEntry(pack, seq, length));
				packconsumer.accept(pack);
			}
		}
		}finally {
			rlock.unlock();
		}
		return true;
	}
}
