/*
 * Copyright 2015-present 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 com.google.common.base.MoreObjects.toStringHelper;
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();
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("[");
            sb.append("type= ");
            sb.append(type);
            sb.append("data= ");
            sb.append(data);
            sb.append("]");
            return sb.toString();
        }
    }

    /**
     * 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;
        };
    }

    @Override
    public String toString() {
        return toStringHelper(getClass())
                .toString();
        // TODO: need to handle options
    }
}
