package org.kne.cloud.network.srv6;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Serializable;
import java.net.Inet6Address;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Set;

import org.kne.cloud.network.NetworkPacket;
import org.kne.cloud.network.ipv6.IPv6AddressGroup;

public class RouterInfo implements Serializable{

	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private IPv6AddressGroup locator;
	private long asn;
	public IPv6AddressGroup getLocator() {
		return locator;
	}
	public void setLocator(IPv6AddressGroup locator) {
		this.locator = locator;
	}
	
	public long getAsn() {
		return asn;
	}
	public void setAsn(long asn) {
		this.asn = asn;
	}
	@Override
	public int hashCode() {
		return Objects.hash(locator, neighborAddresses);
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		RouterInfo other = (RouterInfo) obj;
		return Objects.equals(locator, other.locator) && Objects.equals(neighborAddresses, other.neighborAddresses);
	}
	private List<NeighborInfo> neighborAddresses=new ArrayList<>();
	private long createTime;
	
	
	public long getCreateTime() {
		return createTime;
	}
	private static final long INFO_UPDATETIME=10000000000L;
	private static final long INFO_TIMEOUT=60000000000L;
	private long putTime=System.nanoTime();
	public boolean checkUpdateTime() {
		return System.nanoTime()-putTime>INFO_UPDATETIME;
	}
	
	public boolean checkTimeOut() {
		return System.nanoTime()-putTime>INFO_TIMEOUT;
	}
	
	public boolean checkTimeOut(long timeout) {
		return System.nanoTime()-putTime>timeout;
	}
	
	@Override
	public String toString() {
		return "RINFO [locator=" + locator + ", neighborAddresses=" + neighborAddresses + ", putTime=" + putTime
				+ "]";
	}
	public List<NeighborInfo> getNeighborAddresses() {
		return neighborAddresses;
	}
	
	public RouterInfo( long createTime,IPv6AddressGroup locator,long asn) {
		this.createTime = createTime;
		this.locator=locator;
		this.asn=asn;
	}

	public RouterInfo() {
	}
	public void writeToStream(DataOutputStream out) throws IOException {
		locator.writeToStream(out);
		out.writeLong(asn);
		out.writeLong(createTime);
		out.writeInt(neighborAddresses.size());
		for(	NeighborInfo neighborInfo :neighborAddresses) {
			neighborInfo.writeToStream(out);
		}
	}
	
	protected void writeToChannel(WritableByteChannel dto) throws IOException {
		writeToStream(new DataOutputStream( Channels.newOutputStream(dto)));
	}
	protected void readFromChannel(ReadableByteChannel din, long length) throws IOException {
		readFromStream(new DataInputStream(Channels.newInputStream(din)));
	}
	public void readFromStream(DataInputStream in) throws IOException {
		locator=new IPv6AddressGroup(in);
		asn=in.readLong();
		createTime=in.readLong();
		int size=in.readInt();
		neighborAddresses=new ArrayList<>(size);
		for (int i = 0; i < size; i++) {
			NeighborInfo nif=new NeighborInfo();
			nif.readFromStream(in);
			neighborAddresses.add(nif);
			
		}
	}
	
}
