package org.kne.cloud.network.srv6;

import java.io.IOException;
import java.lang.ref.Cleaner;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.function.BiConsumer;

import org.kne.cloud.network.klalb.KLALBController;
import org.kne.opencl64.Releaser;

public class KLALBRoutingProtocolAPIServer {
	private KLALBController controller;
	private KLALBRoutingProtocol routingProtocol;
	

	private static final Cleaner clr=Cleaner.create();
	
	private BiConsumer<SocketAddress, JsonDataPacket> rec=(addr,data)->{
		try {
		KLALBRoutingProtocolJsonData dataobj= data.getDecodedData();
		InetSocketAddress addrs=(InetSocketAddress) addr;
		switch(dataobj.getType()){
		case KLALBRoutingProtocolJsonData.NODE_INFO_TINY_REQ:
			// 精简查询：仅返回设备名称（设备名称随路由信息广播公开，不受 denyExternalEndpointQuery 限制）
			KLALBRoutingProtocolJsonData tinyjson=new KLALBRoutingProtocolJsonData(KLALBRoutingProtocolJsonData.NODE_INFO_TINY_RESP,dataobj.getUuid(),null);
			tinyjson.setDeviceName(controller.getIpv6Router().getDeviceName());
			routingProtocol.sendJsonPacketToAddress(new JsonDataPacket(tinyjson),addr);
			break;
		case KLALBRoutingProtocolJsonData.NODE_INFO_FULL_REQ:
			// 完整查询：设备名称与描述总是正常响应；denyExternalEndpointQuery 仅隐藏外部端点列表
			boolean denyEndpoints=controller.getConfigItem()!=null&&controller.getConfigItem().isDenyExternalEndpointQuery();
			KLALBRoutingProtocolJsonData json=new KLALBRoutingProtocolJsonData(KLALBRoutingProtocolJsonData.NODE_INFO_FULL_RESP,dataobj.getUuid(),denyEndpoints?null:controller.getExternalEndpoints());
			json.setDeviceName(controller.getIpv6Router().getDeviceName());// 附带本机设备名称
			if(controller.getConfigItem()!=null) {
				json.setDeviceDescription(controller.getConfigItem().getDeviceDescription());// 附带本机设备描述
			}
			routingProtocol.sendJsonPacketToAddress(new JsonDataPacket(json),addr);
			break;
		}
		} catch (IOException e) {
			e.printStackTrace();
		}
	};

	public KLALBRoutingProtocolAPIServer(KLALBRoutingProtocol routingProtocol,KLALBController controller) {
		this.controller=controller;
		this.routingProtocol=routingProtocol;
		routingProtocol.addReceiver(rec);
		this.releaser=new KLALBRoutingProtocolAPIServerReleaser(this.routingProtocol,rec);
		clr.register(this, releaser);
	}

	public KLALBController getController() {
		return controller;
	}

	public KLALBRoutingProtocol getRoutingProtocol() {
		return routingProtocol;
	}
	
	
private KLALBRoutingProtocolAPIServerReleaser releaser;
	
	public void close() {
		releaser.run();
	}
	
	
	public boolean isClosed() {
		return releaser.isReleased();
	}
	
}
class KLALBRoutingProtocolAPIServerReleaser extends Releaser<BiConsumer<SocketAddress, JsonDataPacket>>{

	private KLALBRoutingProtocol routingProtocol;

	public KLALBRoutingProtocolAPIServerReleaser(KLALBRoutingProtocol routingProtocol,BiConsumer<SocketAddress, JsonDataPacket> resource) {
		super(resource);
		this.routingProtocol=routingProtocol;
	}

	@Override
	protected void release(BiConsumer<SocketAddress, JsonDataPacket> resource) {
		routingProtocol.removeReceiver(resource);
	}
}