/*
 * Copyright 2015 Open Networking Laboratory
 *
 * 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.ndp;

import org.onlab.packet.BasePacket;
import org.onlab.packet.DeserializationException;
import org.onlab.packet.Deserializer;
import org.onlab.packet.IPacket;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static org.onlab.packet.PacketUtils.checkInput;

/**
 * Neighbor Discovery Protocol packet options.
 */
public class NeighborDiscoveryOptions extends BasePacket {
    public static final byte TYPE_SOURCE_LL_ADDRESS = 1;
    public static final byte TYPE_TARGET_LL_ADDRESS = 2;
    public static final byte TYPE_PREFIX_INFORMATION = 3;
    public static final byte TYPE_REDIRECTED_HEADER = 4;
    public static final byte TYPE_MTU = 5;

    public static final byte INITIAL_HEADER_REQUIRED = 2;

    private static final String BUFFER_UNDERFLOW_ERROR =
            "Not enough bytes in buffer to read option";

    private final List<Option> options = new ArrayList<>();

    /**
     * Packet option.
     */
    public final class Option {
        private final byte type;
        private final byte[] data;

        /**
         * Constructor.
         *
         * @param type the option type
         * @param data the option data
         */
        private Option(byte type, byte[] data) {
            this.type = type;
            this.data = Arrays.copyOfRange(data, 0, data.length);
        }

        /**
         * Gets the option type.
         *
         * @return the option type
         */
        public byte type() {
            return this.type;
        }

        /**
         * Gets the option data.
         *
         * @return the option data
         */
        public byte[] data() {
            return this.data;
        }

        /**
         * Gets the option data length (in number of octets).
         *
         * @return the option data length (in number of octets)
         */
        public int dataLength() {
            return data.length;
        }

        /**
         * Gets the option length (in number of octets), including the type and
         * length fields (one octet each).
         *
         * @return the option length (in number of octets), including the type
         * and length fields
         */
        private int optionLength() {
            return 2 + dataLength();
        }

        /**
         * Gets the option length field value (in units of 8 octets).
         *
         * @return the option length field value (in units of 8 octets)
         */
        private byte optionLengthField() {
            return (byte) ((optionLength() + 7) / 8);
        }

        /**
         * Gets the option length on the wire (in number of octets).
         *
         * @return the option length on the wire (in number of octets)
         */
        private int optionWireLength() {
            return 8 * optionLengthField();
        }
    }

    /**
     * Adds a Neighbor Discovery Protocol packet option.
     *
     * @param type the option type
     * @param data the option data
     * @return this
     */
    public NeighborDiscoveryOptions addOption(byte type, byte[] data) {
        options.add(new Option(type, data));
        return this;
    }

    /**
     * Gets the Neighbor Discovery Protocol packet options.
     *
     * @return the Neighbor Discovery Protocol packet options
     */
    public List<NeighborDiscoveryOptions.Option> options() {
        return this.options;
    }

    /**
     * Checks whether any options are included.
     *
     * @return true if options are included, otherwise false
     */
    public boolean hasOptions() {
        return !this.options.isEmpty();
    }

    @Override
    public byte[] serialize() {
        // Compute first the total length on the wire for all options

        int wireLength = 0;

        for (Option option : this.options) {
            wireLength += option.optionWireLength();
        }

        final byte[] data = new byte[wireLength];
        final ByteBuffer bb = ByteBuffer.wrap(data);

        //
        // Serialize all options
        //
        for (Option option : this.options) {
            bb.put(option.type());
            bb.put(option.optionLengthField());
            bb.put(option.data());
            // Add the padding
            int paddingLength =
                option.optionWireLength() - option.optionLength();
            for (int i = 0; i < paddingLength; i++) {
                bb.put((byte) 0);
            }
        }

        return data;
    }

    @Override
    public IPacket deserialize(byte[] data, int offset, int length) {
        final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);

        options.clear();

        //
        // Deserialize all options
        //
        while (bb.hasRemaining()) {
            byte type = bb.get();
            if (!bb.hasRemaining()) {
                break;
            }
            byte lengthField = bb.get();
            int dataLength = lengthField * 8;   // The data length field is in
            // unit of 8 octets

            // Exclude the type and length fields
            if (dataLength < 2) {
                break;
            }
            dataLength -= 2;

            if (bb.remaining() < dataLength) {
                break;
            }
            byte[] optionData = new byte[dataLength];
            bb.get(optionData, 0, optionData.length);
            addOption(type, optionData);
        }

        return this;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;

        for (Option option : this.options) {
            result = prime * result + option.type();
            result = prime * result + Arrays.hashCode(option.data());
        }
        return result;
    }

    @Override
    public boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj instanceof NeighborDiscoveryOptions) {
            NeighborDiscoveryOptions other = (NeighborDiscoveryOptions) obj;
            return this.options.equals(other.options);
        }
        return false;
    }

    public static Deserializer<NeighborDiscoveryOptions> deserializer() {
        return (data, offset, length) -> {
            checkInput(data, offset, length, INITIAL_HEADER_REQUIRED);

            final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);

            NeighborDiscoveryOptions ndo = new NeighborDiscoveryOptions();

            ndo.options.clear();

            //
            // Deserialize all options
            //
            while (bb.hasRemaining()) {
                byte type = bb.get();
                if (!bb.hasRemaining()) {
                    throw new DeserializationException(BUFFER_UNDERFLOW_ERROR);
                }
                byte lengthField = bb.get();
                int dataLength = lengthField * 8;   // The data length field is in
                // unit of 8 octets

                // Exclude the type and length fields
                if (dataLength < 2) {
                    break;
                }
                dataLength -= 2;

                if (bb.remaining() < dataLength) {
                    throw new DeserializationException(BUFFER_UNDERFLOW_ERROR);
                }
                byte[] optionData = new byte[dataLength];
                bb.get(optionData, 0, optionData.length);
                ndo.addOption(type, optionData);
            }

            return ndo;
        };
    }
}
