/*
 * Copyright 2017-present Open Networking Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.onlab.packet;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import org.onlab.packet.dhcp.Dhcp6ClientIdOption;
import org.onlab.packet.dhcp.Dhcp6IaAddressOption;
import org.onlab.packet.dhcp.Dhcp6IaNaOption;
import org.onlab.packet.dhcp.Dhcp6IaTaOption;
import org.onlab.packet.dhcp.Dhcp6IaPdOption;
import org.onlab.packet.dhcp.Dhcp6Option;
import org.onlab.packet.dhcp.Dhcp6RelayOption;
import org.onlab.packet.dhcp.Dhcp6InterfaceIdOption;

import java.nio.ByteBuffer;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;

/**
 * Representation of an DHCPv6 Packet.
 * Base on RFC-3315.
 */
public class DHCP6 extends BasePacket {
    private static final int UNSIGNED_SHORT_MASK = 0xffff;
    // size of different field of option
    private static final int OPT_CODE_SIZE = 2;
    private static final int OPT_LEN_SIZE = 2;

    // default size of DHCPv6 payload (without options)
    private static final int DHCP6_DEFAULT_SIZE = 4;

    // default size of DHCPv6 relay message payload (without options)
    private static final int DHCP6_RELAY_MSG_SIZE = 34;
    private static final int IPV6_ADDR_LEN = 16;

    // masks & offsets for default DHCPv6 header
    private static final int MSG_TYPE_OFFSET = 24;
    private static final int TRANSACTION_ID_MASK = 0x00ffffff;

    // Relay message types
    public static final Set<Byte> RELAY_MSG_TYPES =
            ImmutableSet.of(MsgType.RELAY_FORW.value,
                            MsgType.RELAY_REPL.value);

    /**
     * DHCPv6 message type.
     */
    public enum MsgType {
        SOLICIT((byte) 1), ADVERTISE((byte) 2), REQUEST((byte) 3),
        CONFIRM((byte) 4), RENEW((byte) 5), REBIND((byte) 6),
        REPLY((byte) 7), RELEASE((byte) 8), DECLINE((byte) 9),
        RECONFIGURE((byte) 10), INFORMATION_REQUEST((byte) 11),
        RELAY_FORW((byte) 12), RELAY_REPL((byte) 13);

        protected byte value;
        MsgType(final byte value) {
            this.value = value;
        }
        public byte value() {
            return this.value;
        }
        public static MsgType getType(final int value) {
            switch (value) {
                case 1:
                    return SOLICIT;
                case 2:
                    return ADVERTISE;
                case 3:
                    return REQUEST;
                case 4:
                    return CONFIRM;
                case 5:
                    return RENEW;
                case 6:
                    return REBIND;
                case 7:
                    return REPLY;
                case 8:
                    return RELEASE;
                case 9:
                    return DECLINE;
                case 10:
                    return RECONFIGURE;
                case 11:
                    return INFORMATION_REQUEST;
                case 12:
                    return RELAY_FORW;
                case 13:
                    return RELAY_REPL;
                default:
                    return null;
            }
        }
        public static String  getMsgTypeStr(final MsgType msgType) {
            switch (msgType) {
                case SOLICIT:
                    return "SOLICIT";
                case ADVERTISE:
                    return "ADVERTISE";
                case REQUEST:
                    return "REQUEST";
                case CONFIRM:
                    return "CONFIRM";
                case RENEW:
                    return "RENEW";
                case REBIND:
                    return "REBIND";
                case REPLY:
                    return "REPLY";
                case RELEASE:
                    return "RELEASE";
                case DECLINE:
                    return "DECLINE";
                case RECONFIGURE:
                    return "RECONFIGURE";
                case INFORMATION_REQUEST:
                    return "INFORMATION_REQUEST";
                case RELAY_FORW:
                    return "RELAY_FORW";
                case RELAY_REPL:
                    return "RELAY_REPL";
                default:
                    return "NULL";
            }
        }
    }

    /**
     * DHCPv6 option code.
     */
    public enum OptionCode {
        CLIENTID((short) 1), SERVERID((short) 2), IA_NA((short) 3), IA_TA((short) 4),
        IAADDR((short) 5), ORO((short) 6), PREFERENCE((short) 7), ELAPSED_TIME((short) 8),
        RELAY_MSG((short) 9), AUTH((short) 11), UNICAST((short) 12),
        STATUS_CODE((short) 13), RAPID_COMMIT((short) 14), USER_CLASS((short) 15),
        VENDOR_CLASS((short) 16), VENDOR_OPTS((short) 17), INTERFACE_ID((short) 18),
        RECONF_MSG((short) 19), RECONF_ACCEPT((short) 20), IA_PD((short) 25), IAPREFIX((short) 26),
        SUBSCRIBER_ID((short) 38);

        protected short value;
        OptionCode(final short value) {
            this.value = value;
        }
        public short value() {
            return this.value;
        }
    }

    private static final Map<Short, Deserializer<Dhcp6Option>> OPT_DESERIALIZERS =
            ImmutableMap.<Short, Deserializer<Dhcp6Option>>builder()
                            .put(OptionCode.IA_NA.value, Dhcp6IaNaOption.deserializer())
                            .put(OptionCode.IA_TA.value, Dhcp6IaTaOption.deserializer())
                            .put(OptionCode.IAADDR.value, Dhcp6IaAddressOption.deserializer())
                            .put(OptionCode.RELAY_MSG.value, Dhcp6RelayOption.deserializer())
                            .put(OptionCode.CLIENTID.value, Dhcp6ClientIdOption.deserializer())
                            .put(OptionCode.IA_PD.value, Dhcp6IaPdOption.deserializer())
                            .put(OptionCode.INTERFACE_ID.value, Dhcp6InterfaceIdOption.deserializer())
                    .build();

    // general field
    private byte msgType; // 1 byte
    private List<Dhcp6Option> options;

    // non-relay field
    private int transactionId; // 3 bytes

    // relay field
    private byte hopCount; // 1 byte
    private byte[] linkAddress; // 16 bytes
    private byte[] peerAddress; // 16 bytes

    /**
     * Creates new DHCPv6 object.
     */
    public DHCP6() {
        options = Lists.newArrayList();
    }

    @Override
    public byte[] serialize() {
        int payloadLength = options.stream()
                .mapToInt(Dhcp6Option::getLength)
                .sum();

        // 2 bytes code and 2 bytes length
        payloadLength += options.size() * (OPT_CODE_SIZE + OPT_LEN_SIZE);

        if (RELAY_MSG_TYPES.contains(msgType)) {
            payloadLength += DHCP6_RELAY_MSG_SIZE;
        } else {
            payloadLength += DHCP6_DEFAULT_SIZE;
        }

        ByteBuffer bb = ByteBuffer.allocate(payloadLength);

        if (RELAY_MSG_TYPES.contains(msgType)) {
            bb.put(msgType);
            bb.put(hopCount);
            bb.put(linkAddress);
            bb.put(peerAddress);
        } else {
            int defaultHeader = ((int) msgType) << MSG_TYPE_OFFSET | (transactionId & TRANSACTION_ID_MASK);
            bb.putInt(defaultHeader);
        }

        // serialize options
        options.forEach(option -> {
            bb.put(option.serialize());
        });

        return bb.array();
    }

    /**
     * Returns a deserializer for DHCPv6.
     *
     * @return the deserializer for DHCPv6
     */
    public static Deserializer<DHCP6> deserializer() {
        return (data, offset, length) -> {
            DHCP6 dhcp6 = new DHCP6();

            checkNotNull(data);

            if (offset < 0 || length < 0 ||
                    length > data.length || offset >= data.length ||
                    offset + length > data.length) {
                throw new DeserializationException("Illegal offset or length");
            }

            final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
            if (bb.remaining() < DHCP6.DHCP6_DEFAULT_SIZE) {
                throw new DeserializationException(
                        "Buffer underflow while reading DHCPv6 option");
            }

            // peek message type
            dhcp6.msgType = bb.array()[offset];
            if (RELAY_MSG_TYPES.contains(dhcp6.msgType)) {
                bb.get(); // drop message type
                dhcp6.hopCount = bb.get();
                dhcp6.linkAddress = new byte[IPV6_ADDR_LEN];
                dhcp6.peerAddress = new byte[IPV6_ADDR_LEN];

                bb.get(dhcp6.linkAddress);
                bb.get(dhcp6.peerAddress);
            } else {
                // get msg type + transaction id (1 + 3 bytes)
                int defaultHeader = bb.getInt();
                dhcp6.transactionId = defaultHeader & TRANSACTION_ID_MASK;
            }

            dhcp6.options = Lists.newArrayList();
            while (bb.remaining() >= Dhcp6Option.DEFAULT_LEN) {
                // create temporary byte buffer for reading code and length
                ByteBuffer optByteBuffer =
                        ByteBuffer.wrap(data, bb.position(), bb.limit() - bb.position());
                short code = optByteBuffer.getShort();
                int optionLen = UNSIGNED_SHORT_MASK & optByteBuffer.getShort();
                if (optByteBuffer.remaining() < optionLen) {
                    throw new DeserializationException(
                            "Buffer underflow while reading DHCPv6 option");
                }
                Dhcp6Option option;
                byte[] optionData = new byte[Dhcp6Option.DEFAULT_LEN + optionLen];
                bb.get(optionData);
                if (OPT_DESERIALIZERS.containsKey(code)) {
                    option = OPT_DESERIALIZERS.get(code).deserialize(optionData, 0, optionData.length);
                } else {
                    option = Dhcp6Option.deserializer().deserialize(optionData, 0, optionData.length);
                }
                option.setParent(dhcp6);
                dhcp6.options.add(option);
            }

            return dhcp6;
        };
    }


    /**
     * Gets the message type of this DHCPv6 packet.
     *
     * @return the message type
     */
    public byte getMsgType() {
        return msgType;
    }

    /**
     * Gets options from this DHCPv6 packet.
     *
     * @return DHCPv6 options
     */
    public List<Dhcp6Option> getOptions() {
        return options;
    }

    /**
     * Gets the transaction ID of this DHCPv6 packet.
     *
     * @return the transaction ID
     */
    public int getTransactionId() {
        return transactionId;
    }

    /**
     * Gets the hop count of this DHCPv6 relay message.
     *
     * @return the hop count
     */
    public byte getHopCount() {
        return hopCount;
    }

    /**
     * Gets the link address of this DHCPv6 relay message.
     *
     * @return the link address
     */
    public byte[] getLinkAddress() {
        return linkAddress;
    }

    /**
     * Gets IPv6 link address.
     *
     * @return the IPv6 link address
     */
    public Ip6Address getIp6LinkAddress() {
        return linkAddress == null ? null : Ip6Address.valueOf(linkAddress);
    }

    /**
     * Gets the peer address of this DHCPv6 relay message.
     *
     * @return the link address
     */
    public byte[] getPeerAddress() {
        return peerAddress;
    }

    /**
     * Gets IPv6 peer address.
     *
     * @return the IPv6 peer address
     */
    public Ip6Address getIp6PeerAddress() {
        return peerAddress == null ? null : Ip6Address.valueOf(peerAddress);
    }

    /**
     * Sets message type.
     *
     * @param msgType the message type
     */
    public void setMsgType(byte msgType) {
        this.msgType = msgType;
    }

    /**
     * Sets options.
     *
     * @param options the options
     */
    public void setOptions(List<Dhcp6Option> options) {
        this.options = options;
    }

    /**
     * Sets transaction id.
     *
     * @param transactionId the transaction id
     */
    public void setTransactionId(int transactionId) {
        this.transactionId = transactionId;
    }

    /**
     * Sets hop count.
     *
     * @param hopCount the hop count
     */
    public void setHopCount(byte hopCount) {
        this.hopCount = hopCount;
    }

    /**
     * Sets link address.
     *
     * @param linkAddress the link address
     */
    public void setLinkAddress(byte[] linkAddress) {
        this.linkAddress = linkAddress;
    }

    /**
     * Sets peer address.
     *
     * @param peerAddress the peer address
     */
    public void setPeerAddress(byte[] peerAddress) {
        this.peerAddress = peerAddress;
    }

    @Override
    public String toString() {
        if (RELAY_MSG_TYPES.contains(msgType)) {
            // relay message
            return toStringHelper(getClass())
                    .add("msgType", msgType)
                    .add("hopCount", hopCount)
                    .add("linkAddress", Ip6Address.valueOf(linkAddress))
                    .add("peerAddress", Ip6Address.valueOf(peerAddress))
                    .add("options", options)
                    .toString();
        } else {
            return toStringHelper(getClass())
                    .add("msgType", msgType)
                    .add("transactionId", transactionId)
                    .add("options", options)
                    .toString();
        }
    }
}
