package org.kne.cloud.network.ipv6;

import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicLong;

import org.kne.cloud.network.klalb.KLALBUtils;

/**
 * 高性能IPv6地址实现，使用两个long代替byte[16]，
 * 大幅减少GC压力和提高路由表查找性能
 */
public final class IPv6Address implements Comparable<IPv6Address> {
    
    private final long high;
    private final long low;
    
    // 常用常量地址
    public static final IPv6Address LOOPBACK = new IPv6Address(0, 1);
    public static final IPv6Address UNSPECIFIED = new IPv6Address(0, 0);
    public static final IPv6Address LOCALHOST = LOOPBACK;
    
    // IPv4映射的IPv6地址前缀
    private static final long IPV4_MAPPED_HIGH = 0x0000_0000_0000_0000L;
    private static final long IPV4_MAPPED_LOW_PREFIX = 0x0000_0000_FFFF_0000L;
    
    // 构造方法
    public IPv6Address(long high, long low) {
        this.high = high;
        this.low = low;
    }
    
    public IPv6Address(Inet6Address address) {
    	this(address.getAddress());
	}

	public IPv6Address(byte[] bytes) {
		  if (bytes.length != 16) {
	            throw new IllegalArgumentException("IPv6 address must be 16 bytes");
	        }
	        
	        this. high = ((long)(bytes[0] & 0xFF) << 56) |
	                   ((long)(bytes[1] & 0xFF) << 48) |
	                   ((long)(bytes[2] & 0xFF) << 40) |
	                   ((long)(bytes[3] & 0xFF) << 32) |
	                   ((long)(bytes[4] & 0xFF) << 24) |
	                   ((long)(bytes[5] & 0xFF) << 16) |
	                   ((long)(bytes[6] & 0xFF) << 8) |
	                   ((long)(bytes[7] & 0xFF));
	        
	        this.low = ((long)(bytes[8] & 0xFF) << 56) |
	                  ((long)(bytes[9] & 0xFF) << 48) |
	                  ((long)(bytes[10] & 0xFF) << 40) |
	                  ((long)(bytes[11] & 0xFF) << 32) |
	                  ((long)(bytes[12] & 0xFF) << 24) |
	                  ((long)(bytes[13] & 0xFF) << 16) |
	                  ((long)(bytes[14] & 0xFF) << 8) |
	                  ((long)(bytes[15] & 0xFF));
	}

	/**
     * 从两个long创建IPv6地址
     */
    public static IPv6Address valueOf(long high, long low) {
        return new IPv6Address(high, low);
    }
    
    /**
     * 从byte[16]创建IPv6地址（高性能版本）
     */
    public static IPv6Address valueOf(byte[] bytes) {
      return new IPv6Address(bytes);
    }
    
    /**
     * 从ByteBuffer创建IPv6地址（零拷贝友好）
     */
    public static IPv6Address valueOf(ByteBuffer buffer) {
        if (buffer.remaining() < 16) {
            throw new IllegalArgumentException("Buffer must have at least 16 bytes remaining");
        }
        
        long high = buffer.getLong();
        long low = buffer.getLong();
        return valueOf(high, low);
    }
    

	public static IPv6Address valueOf(int offset, ByteBuffer buffer) {
		long high = buffer.getLong(offset);
        long low = buffer.getLong(offset+8);
        return valueOf(high, low);
	}
    
    /**
     * 从字符串解析IPv6地址（高性能版本）
     * @throws UnknownHostException 
     */
    public static IPv6Address valueOf(String ipString) throws UnknownHostException {
        if (ipString == null || ipString.isEmpty()) {
            throw new IllegalArgumentException("Invalid IPv6 address string");
        }
    
		return new IPv6Address((Inet6Address)Inet6Address.getByName(ipString));
	
    }
    
    /**
     * 从Java InetAddress转换
     */
    public static IPv6Address valueOf(InetAddress inetAddress) {
        if (inetAddress == null) {
            throw new IllegalArgumentException("InetAddress cannot be null");
        }
        
        byte[] bytes = inetAddress.getAddress();
        if (bytes.length == 4) {
            // IPv4地址，转换为IPv4映射的IPv6地址
            return valueOf(IPV4_MAPPED_HIGH, 
                          IPV4_MAPPED_LOW_PREFIX | 
                          (((long)(bytes[0] & 0xFF) << 24) |
                           ((bytes[1] & 0xFF) << 16) |
                           ((bytes[2] & 0xFF) << 8) |
                           (bytes[3] & 0xFF)));
        }
        
        return valueOf(bytes);
    }
    
    // 核心getter方法
    public long getHigh() {
        return high;
    }
    
    public long getLow() {
        return low;
    }
    
    /**
     * 转换为byte[16]（需要时使用）
     */
    public byte[] toByteArray() {
        byte[] bytes = new byte[16];
        toByteArray(bytes, 0);
        return bytes;
    }
    
    /**
     * 写入到现有byte数组（避免创建新对象）
     */
    public void toByteArray(byte[] dest, int offset) {
        if (dest.length - offset < 16) {
            throw new IllegalArgumentException("Destination array too small");
        }
        
        dest[offset]     = (byte) (high >> 56);
        dest[offset + 1] = (byte) (high >> 48);
        dest[offset + 2] = (byte) (high >> 40);
        dest[offset + 3] = (byte) (high >> 32);
        dest[offset + 4] = (byte) (high >> 24);
        dest[offset + 5] = (byte) (high >> 16);
        dest[offset + 6] = (byte) (high >> 8);
        dest[offset + 7] = (byte) high;
        
        dest[offset + 8]  = (byte) (low >> 56);
        dest[offset + 9]  = (byte) (low >> 48);
        dest[offset + 10] = (byte) (low >> 40);
        dest[offset + 11] = (byte) (low >> 32);
        dest[offset + 12] = (byte) (low >> 24);
        dest[offset + 13] = (byte) (low >> 16);
        dest[offset + 14] = (byte) (low >> 8);
        dest[offset + 15] = (byte) low;
    }
    
    /**
     * 写入到ByteBuffer（高性能网络操作）
     */
    public void writeTo(ByteBuffer buffer) {
        buffer.putLong(high);
        buffer.putLong(low);
    }
    
    
	public void writeTo(int offset, ByteBuffer buffer) {
		 buffer.putLong(offset,high);
	        buffer.putLong(offset+8,low);
	}
    /**
     * 转换为标准IPv6字符串表示
     */
    @Override
    public String toString() {
        try {
			return Inet6Address.getByAddress(toByteArray()).getHostAddress();
		} catch (UnknownHostException e) {
			return "Internal Error";
		}
    }
    
    /**
     * 转换为压缩形式的字符串（::格式）
     */
    public String toCompressedString() {
        return KLALBUtils.parseAbbrIPv6(toString());
    }
    
    /**
     * 检查是否为IPv4映射地址
     */
    public boolean isIPv4MappedAddress() {
        return high == IPV4_MAPPED_HIGH && 
               (low & 0x0000_0000_FFFF_0000L) == IPV4_MAPPED_LOW_PREFIX;
    }
    
    /**
     * 如果这是IPv4映射地址，提取IPv4部分
     */
    public byte[] getIPv4Bytes() {
        if (!isIPv4MappedAddress()) {
            throw new IllegalStateException("Not an IPv4 mapped address");
        }
        
        byte[] ipv4 = new byte[4];
        ipv4[0] = (byte) (low >> 24);
        ipv4[1] = (byte) (low >> 16);
        ipv4[2] = (byte) (low >> 8);
        ipv4[3] = (byte) low;
        
        return ipv4;
    }
    
    /**
     * 检查是否为多播地址
     */
    public boolean isMulticastAddress() {
        return (high & 0xFF00_0000_0000_0000L) == 0xFF00_0000_0000_0000L;
    }
    
    /**
     * 检查是否为链路本地地址
     */
    public boolean isLinkLocalAddress() {
        return (high & 0xFFC0_0000_0000_0000L) == 0xFE80_0000_0000_0000L;
    }
    
    /**
     * 检查是否为站点本地地址（已弃用，但为了兼容性保留）
     */
    public boolean isSiteLocalAddress() {
        return (high & 0xFFC0_0000_0000_0000L) == 0xFEC0_0000_0000_0000L;
    }
    
    /**
     * 检查是否为唯一本地地址 (ULA)
     */
    public boolean isUniqueLocalAddress() {
        return (high & 0xFE00_0000_0000_0000L) == 0xFC00_0000_0000_0000L;
    }
    
    /**
     * 检查是否为环回地址
     */
    public boolean isLoopbackAddress() {
        return this.equals(LOOPBACK);
    }
    
    /**
     * 检查是否为未指定地址
     */
    public boolean isUnspecifiedAddress() {
        return this.equals(UNSPECIFIED);
    }
    
    /**
     * 获取多播地址的scope
     */
    public int getMulticastScope() {
        if (!isMulticastAddress()) {
            return -1;
        }
        return (int) ((low >> 48) & 0x0F);
    }
    
    // 路由表相关的实用方法
    
    /**
     * 创建掩码（用于CIDR表示法）
     */
    public static IPv6Address createMask(int prefixLength) {
        if (prefixLength < 0 || prefixLength > 128) {
            throw new IllegalArgumentException("Prefix length must be between 0 and 128");
        }
        
        long maskHigh, maskLow;
        if (prefixLength == 128) {
            maskHigh = -1L;  // 0xFFFFFFFF_FFFFFFFF
            maskLow = -1L;
        } else if (prefixLength > 64) {
            maskHigh = -1L;
            maskLow = (-1L) << (64 - (prefixLength - 64));
        } else if (prefixLength == 64) {
            maskHigh = -1L;
            maskLow = 0;
        } else {
            maskHigh = (-1L) << (64 - prefixLength);
            maskLow = 0;
        }
        
        return valueOf(maskHigh, maskLow);
    }
    
    /**
     * 应用掩码（用于网络地址计算）
     */
    public IPv6Address maskWith(IPv6Address mask) {
        return valueOf(high & mask.high, low & mask.low);
    }
    
    /**
     * 检查地址是否在指定网络内
     */
    public boolean isInNetwork(IPv6Address network, IPv6Address mask) {
        IPv6Address maskedThis = this.maskWith(mask);
        IPv6Address maskedNetwork = network.maskWith(mask);
        return maskedThis.equals(maskedNetwork);
    }
    
    /**
     * 检查地址是否在指定CIDR网络内
     */
    public boolean isInNetwork(IPv6Address network, int prefixLength) {
        IPv6Address mask = createMask(prefixLength);
        return isInNetwork(network, mask);
    }
    
    // 比较和哈希
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        
        IPv6Address other = (IPv6Address) obj;
        return high == other.high && low == other.low;
    }
    
    @Override
    public int hashCode() {
        // 优化的哈希计算，考虑long的分布
        return (int) (high ^ (high >>> 32) ^ low ^ (low >>> 32));
    }
    
    @Override
    public int compareTo(IPv6Address other) {
        int highCompare = Long.compareUnsigned(high, other.high);
        if (highCompare != 0) return highCompare;
        return Long.compareUnsigned(low, other.low);
    }
    
    public static void main(String[] args) throws UnknownHostException {
        // 创建IPv6地址
        IPv6Address addr1 = IPv6Address.valueOf("2001:db8::1");
        IPv6Address addr2 = IPv6Address.valueOf(0x20010DB800000000L, 0x0000000000000001L);
        
        // 高性能路由表查找
        IPv6Address target = IPv6Address.valueOf("2001:db8:1234::5678");
        IPv6Address network = IPv6Address.valueOf("2001:db8:1234::");
        int prefixLength = 64;
        
        if (target.isInNetwork(network, prefixLength)) {
            System.out.println("地址在目标网络内");
        }
        
        // 转换为字节数组（需要时）
        byte[] bytes = addr1.toByteArray();
        
        // 直接写入ByteBuffer（零拷贝）
        ByteBuffer buffer = ByteBuffer.allocateDirect(16);
        addr1.writeTo(buffer);
        
    }

	public Inet6Address toInet6Address() {
		try {
			return (Inet6Address) Inet6Address.getByAddress(toByteArray());
		} catch (UnknownHostException e) {
			return null;
		}
	}

	public boolean isAnyLocalAddress() {
		return high==0&&low==0;
	}



}