/*
 * 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 org.slf4j.Logger;

import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Objects;

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

import static org.slf4j.LoggerFactory.getLogger;

/**
 * Default DHCP option.
 */
public class RIPngEntry extends BasePacket {
    public static final int OPT_CODE_LEN = 1;
    public static final int ENTRY_LEN = 20;
    public static final byte INFINITY_METRIC = 16;
    public static final byte NEXTHOP_METRIC =  -128; // actually it is 0xFF

    private final Logger log = getLogger(getClass());
    protected byte[] prefix; // 16 bytes
    protected short routeTag;
    protected byte prefixLen;
    protected byte metric;

    @Override
    public byte[] serialize() {
        ByteBuffer byteBuffer;
        byteBuffer = ByteBuffer.allocate(ENTRY_LEN);
        byteBuffer.put(prefix);
        byteBuffer.putShort(routeTag);
        byteBuffer.put(prefixLen);
        byteBuffer.put(metric);
        return byteBuffer.array();
    }

    /**
     * Deserializer function for RIPng entry.
     *
     * @return deserializer function
     */
    public static Deserializer<RIPngEntry> deserializer() {
        return (data, offset, length) -> {
            RIPngEntry ripngEntry = new RIPngEntry();

            checkNotNull(data);

            if (offset < 0 || length < 0 ||
                length > data.length || offset >= data.length ||
                offset + length > data.length) {
               throw new DeserializationException("Illegal offset or length");
            }
            ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
            if (bb.remaining() < ENTRY_LEN) {
               throw new DeserializationException(
                          "Buffer underflow while reading RIPng entry");
            }
            ripngEntry.prefix = new byte[IpAddress.INET6_BYTE_LENGTH];
            bb.get(ripngEntry.prefix);
            ripngEntry.routeTag = bb.getShort();
            ripngEntry.prefixLen = bb.get();
            ripngEntry.metric = bb.get();
            return ripngEntry;
        };
    }
    /*
     * (non-Javadoc)
     *
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        return Objects.hash(super.hashCode(), metric, prefixLen, Arrays.hashCode(prefix), routeTag);
    }

    /*
     * (non-Javadoc)
     *
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof RIPngEntry)) {
            return false;
        }
        final RIPngEntry that = (RIPngEntry) obj;

        return super.equals(that) &&
                Objects.equals(metric, metric) &&
                Objects.equals(routeTag, that.routeTag) &&
                Objects.equals(prefixLen, that.prefixLen) &&
                Arrays.equals(prefix, that.prefix) &&
                Objects.equals(routeTag, that.routeTag);
    }
    /**
     * @return the IPv6 prefix
     */
    public byte[] getPrefix() {
        return this.prefix;
    }

    /**
     * @param prefix the IPv6 prefix to set
     * @return this
     */
    public RIPngEntry setPrefix(final byte[] prefix) {
        this.prefix = prefix;
        return this;
    }

    /**
     * @return the route tag
     */
    public short getRouteTag() {
        return this.routeTag;
    }

    /**
     * @param routetag the route tag to set
     * @return this
     */
    public RIPngEntry setRouteTag(final short routetag) {
        this.routeTag = routetag;
        return this;
    }

    /**
     * @return the prefix length
     */
    public byte getPrefixLen() {
        return this.prefixLen;
    }

    /**
     * @param prefixlen the prefix length to set
     * @return this
     */
    public RIPngEntry setPrefixLen(final byte prefixlen) {
        this.prefixLen = prefixlen;
        return this;
    }

    /**
     * @return the metric
     */
    public byte getMetric() {
        return this.metric;
    }

    /**
     * @param metric the route metric to set
     * @return this
     */
    public RIPngEntry setMetric(final byte metric) {
        this.metric = metric;
        return this;
    }

    /*
     * (non-Javadoc)
     *
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return "RIPngEntry [prefix=" + this.prefix + ", route tag=" + this.routeTag
                + ", prefix length=" + this.prefixLen
                + ", metric = " + this.metric + "]";
    }
}
