// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)

package org.xbill.DNS;

import java.io.*;
import java.net.*;

/**
 * A6 Record - maps a domain name to an IPv6 address (experimental)
 *
 * @author Brian Wellington
 */

public class A6Record extends Record {

    private static final long serialVersionUID = -8815026887337346789L;

    private int prefixBits;
    private InetAddress suffix;
    private Name prefix;

    A6Record() {
    }

    Record
    getObject() {
        return new A6Record();
    }

    /**
     * Creates an A6 Record from the given data
     *
     * @param prefixBits The number of bits in the address prefix
     * @param suffix     The address suffix
     * @param prefix     The name of the prefix
     */
    public A6Record(Name name, int dclass, long ttl, int prefixBits,
                    InetAddress suffix, Name prefix) {
        super(name, Type.A6, dclass, ttl);
        this.prefixBits = checkU8("prefixBits", prefixBits);
        if (suffix != null && Address.familyOf(suffix) != Address.IPv6)
            throw new IllegalArgumentException("invalid IPv6 address");
        this.suffix = suffix;
        if (prefix != null)
            this.prefix = checkName("prefix", prefix);
    }

    void
    rrFromWire(DNSInput in) throws IOException {
        prefixBits = in.readU8();
        int suffixbits = 128 - prefixBits;
        int suffixbytes = (suffixbits + 7) / 8;
        if (prefixBits < 128) {
            byte[] bytes = new byte[16];
            in.readByteArray(bytes, 16 - suffixbytes, suffixbytes);
            suffix = InetAddress.getByAddress(bytes);
        }
        if (prefixBits > 0)
            prefix = new Name(in);
    }

    void
    rdataFromString(Tokenizer st, Name origin) throws IOException {
        prefixBits = st.getUInt8();
        if (prefixBits > 128) {
            throw st.exception("prefix bits must be [0..128]");
        } else if (prefixBits < 128) {
            String s = st.getString();
            try {
                suffix = Address.getByAddress(s, Address.IPv6);
            } catch (UnknownHostException e) {
                throw st.exception("invalid IPv6 address: " + s);
            }
        }
        if (prefixBits > 0)
            prefix = st.getName(origin);
    }

    /**
     * Converts rdata to a String
     */
    String
    rrToString() {
        StringBuffer sb = new StringBuffer();
        sb.append(prefixBits);
        if (suffix != null) {
            sb.append(" ");
            sb.append(suffix.getHostAddress());
        }
        if (prefix != null) {
            sb.append(" ");
            sb.append(prefix);
        }
        return sb.toString();
    }

    /**
     * Returns the number of bits in the prefix
     */
    public int
    getPrefixBits() {
        return prefixBits;
    }

    /**
     * Returns the address suffix
     */
    public InetAddress
    getSuffix() {
        return suffix;
    }

    /**
     * Returns the address prefix
     */
    public Name
    getPrefix() {
        return prefix;
    }

    void
    rrToWire(DNSOutput out, Compression c, boolean canonical) {
        out.writeU8(prefixBits);
        if (suffix != null) {
            int suffixbits = 128 - prefixBits;
            int suffixbytes = (suffixbits + 7) / 8;
            byte[] data = suffix.getAddress();
            out.writeByteArray(data, 16 - suffixbytes, suffixbytes);
        }
        if (prefix != null)
            prefix.toWire(out, null, canonical);
    }

}
