package org.kne.cloud.network.kltp;

import java.io.IOException;
import java.net.BindException;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

import org.kne.cloud.network.ipv6.IPv6Address;
import org.kne.cloud.network.ipv6.IPv6Packet;
import org.kne.cloud.network.ipv6.IPv6Packet.IPv6Payload;
import org.kne.cloud.network.ipv6.IPv6ProtocolRegister;
import org.kne.cloud.network.klalb.BindableConsumer;
import org.kne.cloud.network.klalb.KLALBController;
import org.kne.cloud.network.klalb.PortBinder;
import org.kne.cloud.network.srv6.IPv6PacketConsumer;

public class KLTPProtocolRegister extends PortBinder<KLTPSessionPacket> implements IPv6ProtocolRegister {
	private KLALBController controller;
	
	public KLTPProtocolRegister(KLALBController controller) {
		super(controller.getSelf().getAddress());
		this.controller = controller;
	}
		private static final boolean showpacket=false;
		private static final boolean debug=false;
		private ConcurrentHashMap<UUID, KLTPPacketConsumer> recvRegisterMap=new ConcurrentHashMap<UUID, KLTPPacketConsumer>();
		private ConcurrentHashMap<UUID, KLTPPacketConsumer> sendRegisterMap=new ConcurrentHashMap<UUID, KLTPPacketConsumer>();
		public void registerReceiveStream(KLTPPacketConsumer kltp) throws BindException {
			if(recvRegisterMap.putIfAbsent(kltp.getStreamUUID(), kltp)!=null) {
				throw new BindException("KLTP receive UUID "+kltp.getStreamUUID()+" already used!");
			}else {
				if(debug)
				System.out.println("接收流打开："+kltp.getStreamUUID());
			}
		}

		public void unregisterReceiveStream(KLTPPacketConsumer kltp) {
			recvRegisterMap.remove(kltp.getStreamUUID(), kltp);
			if(debug)
			System.out.println("接收流关闭："+kltp.getStreamUUID());
		}
		
		public void registerSendStream(KLTPPacketConsumer kltp) throws BindException {
			if(sendRegisterMap.putIfAbsent(kltp.getStreamUUID(), kltp)!=null) {
				throw new BindException("KLTP send UUID "+kltp.getStreamUUID()+" already used!");
			}else {
				if(debug)
				System.out.println("发送流打开："+kltp.getStreamUUID());
			}
		}

		public void unregisterSendStream(KLTPPacketConsumer kltp) {
			sendRegisterMap.remove(kltp.getStreamUUID(), kltp);
			if(debug)
			System.out.println("发送流关闭："+kltp.getStreamUUID());
		}
		
		@Override
		public boolean onaccept(IPv6Packet packx) throws IOException {
			IPv6Payload pl = packx.getPayload();
			if (pl instanceof KLTPPacket) {
				KLTPPacket kltp = (KLTPPacket) pl;
				if (showpacket)
					System.out.println("KLTP_RX:" + kltp);
				if(kltp.getType() ==KLTPPacket.KLTP_TYPE_ACK) {
					KLTPPacketConsumer cosu= sendRegisterMap.get(kltp.getUUID());
					if(cosu!=null) {
						cosu.accept(packx);
						return true;
					}
				}else {
					KLTPPacketConsumer cosu= recvRegisterMap.get(kltp.getUUID());
				if(cosu!=null) {
					cosu.accept(packx);
					return true;
				}else {
					if(kltp.getSequence()==0) {
						IPv6Address srca=packx.getSourceAddress();
						KLTPInputStream kins=new KLTPInputStream(controller, srca, kltp.getUUID());
						kins.accept(packx);
						KLTPSessionPacket sess=new KLTPSessionPacket(kins);
						sess.readFromChannel(kins);
						BindableConsumer<KLTPSessionPacket> con;
						if((con=distributePacketToConsumer(srca, sess))!=null) {
							//System.out.println(this);
							con.accept(sess);
							System.out.println("接受连接："+sess);
							return true;
						}else {
							kins.close();
							System.out.println("丢弃连接："+sess);
						}
						
					}else {
						//System.out.println("丢弃连接："+kltp);
						
					}
				}
				}
				
				
				
			}
			return false;
		}

	}