package org.kne.cloud.network.ipv6;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;

import org.kne.cloud.network.srv6.SRv6Router;

public class LoopbackIPv6NetworkLink extends AbstractIPv6NetworkLink implements IPv6NetworkLink {
	private IPv6NetworkLink fallbackLink;
	
	
		public IPv6NetworkLink getFallbackLink() {
		return fallbackLink;
	}

	public void setFallbackLink(IPv6NetworkLink fallbackLink) {
		this.fallbackLink = fallbackLink;
	}

		private IPv6ProtocolRegister[] protocolNumberRegister = new IPv6ProtocolRegister[256];

		public IPv6ProtocolRegister[] getProtocolNumberRegister() {
			return protocolNumberRegister;
		}
	
		private List<IPv6AddressGroup> addressGroups =new ArrayList<>();
		
		//new Inet6AddressGroup(loopbackAddress, 128) new Inet6AddressGroup((Inet6Address) Inet6Address.getByName("::1"), 128)
		public LoopbackIPv6NetworkLink(List<IPv6AddressGroup> addressGroupsx,SRv6Router router) {
			this.addressGroups .addAll( addressGroupsx);
		}
		
		private Consumer<IPv6Packet> rerouteConsumer;
		private SRv6Router router;

		@Override
		public void sendPacket(IPv6Packet pack, IPv6Address next) throws IOException {
			IPv6ProtocolRegister pcm= protocolNumberRegister[pack.getPayload().getProtocolNumber()];
			if (pcm  != null) {
				if(!pcm.onaccept(pack)) {
					if(fallbackLink!=null) {
						fallbackLink.sendPacket(pack, next);
						}
				}
			}else {
				if(fallbackLink!=null) {
				fallbackLink.sendPacket(pack, next);
				}
			}
		}

		@Override
		public boolean isLoopBack() {
			return true;
		}

		@Override
		public List<Neighbor> getNeighborsInfo() {
			List<Neighbor> hs = new ArrayList<>();
			return hs;
		}


		@Override
		public String getName() {
			return "inLoopBack";
		}

		@Override
		public boolean isUp() {
			return true;
		}

		@Override
		public void setReceiveConsumer(BiConsumer<IPv6NetworkLink,Supplier< IPv6Packet>> con) {
			super.setReceiveConsumer(con);
			if(fallbackLink!=null) {
			fallbackLink.setReceiveConsumer(con);
			}
		}

		@Override
		public List<IPv6AddressGroup> getAddressGroups() {
			return addressGroups;
		}

		public Consumer<IPv6Packet> getRerouteConsumer() {
			return rerouteConsumer;
		}

		@Override
		public List<RouteItem> getRouteItems() {
			List<RouteItem> rlist = new ArrayList<>();
			for(IPv6AddressGroup group:addressGroups) {
			rlist.add(new RouteItem(new IPv6AddressGroup(group.getAddress(), 128),
					group.getAddress(), this, "Direct", 0, 0, null, "D", true));
			}

			for (Iterator<Neighbor> iteratorx = getNeighborsInfo().iterator(); iteratorx.hasNext();) {
				Neighbor addresses = (Neighbor) iteratorx.next();
				RouteItem ri = new RouteItem(new IPv6AddressGroup(addresses.getAddress().getAddress(), 128),
						addresses.getAddress().getAddress(), this, "Direct", 0, 128, null, "D",
						false);
				rlist.add(ri);

				RouteItem ris = new RouteItem(addresses.getLocator(),
						 addresses.getLocator().getAddress(), this, "KLALB SRv6", 13, 128,
						 null, "D", false);
				rlist.add(ris);

			}
			return rlist;
		}


		public SRv6Router getRouter() {
			return router;
		}

		public void setRouter(SRv6Router router) {
			this.router = router;
		}
		

	};