/*
 * Copyright 2016 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.onosproject.bgpio.types;

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

import org.jboss.netty.buffer.ChannelBuffer;
import org.onlab.packet.IpPrefix;
import org.onosproject.bgpio.exceptions.BgpParseException;
import org.onosproject.bgpio.util.Constants;
import org.onosproject.bgpio.util.Validation;

import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;

/**
 * Provides implementation of IPv4AddressTlv.
 */
public class BgpFsDestinationPrefix implements BgpValueType {

    public static final byte FLOW_SPEC_TYPE = Constants.BGP_FLOWSPEC_DST_PREFIX;
    private byte length;
    private IpPrefix ipPrefix;
    public static final int BYTE_IN_BITS = 8;

    /**
     * Constructor to initialize parameters.
     *
     * @param length length of the prefix
     * @param ipPrefix ip prefix
     */
    public BgpFsDestinationPrefix(byte length, IpPrefix ipPrefix) {
        this.ipPrefix = Preconditions.checkNotNull(ipPrefix);
        this.length = length;
    }

    /**
     * Returns ip prefix.
     *
     * @return ipPrefix ip prefix
     */
    public IpPrefix ipPrefix() {
        return ipPrefix;
    }

    @Override
    public short getType() {
        return FLOW_SPEC_TYPE;
    }

    @Override
    public int hashCode() {
        return Objects.hash(ipPrefix);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj instanceof BgpFsDestinationPrefix) {
            BgpFsDestinationPrefix other = (BgpFsDestinationPrefix) obj;
            return Objects.equals(this.ipPrefix, other.ipPrefix);
        }
        return false;
    }

    @Override
    public int write(ChannelBuffer cb) {
        int iLenStartIndex = cb.writerIndex();
        cb.writeByte(FLOW_SPEC_TYPE);
        cb.writeByte(length);
        cb.writeInt(ipPrefix.getIp4Prefix().address().toInt());
        return cb.writerIndex() - iLenStartIndex;
    }

    /**
     * Reads the channel buffer and returns object of IPv4AddressTlv.
     *
     * @param cb channelBuffer
     * @return object of flow spec destination prefix
     * @throws BgpParseException while parsing BgpFsDestinationPrefix
     */
    public static BgpFsDestinationPrefix read(ChannelBuffer cb) throws BgpParseException {
        IpPrefix ipPrefix;

        int length = cb.readByte();
        if (length == 0) {
            byte[] prefix = new byte[] {0};
            ipPrefix = Validation.bytesToPrefix(prefix, length);
            return new BgpFsDestinationPrefix((byte) ipPrefix.prefixLength(), ipPrefix);
        }
        int len = length / BYTE_IN_BITS;
        int reminder = length % BYTE_IN_BITS;
        if (reminder > 0) {
            len = len + 1;
        }
        if (cb.readableBytes() < len) {
            Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
                    BgpErrorType.MALFORMED_ATTRIBUTE_LIST, cb.readableBytes());
        }
        byte[] prefix = new byte[len];
        cb.readBytes(prefix, 0, len);
        ipPrefix = Validation.bytesToPrefix(prefix, length);

        return new BgpFsDestinationPrefix((byte) ipPrefix.prefixLength(), ipPrefix);
    }

    /**
     * Returns object of this class with specified values.
     *
     * @param ipPrefix ip prefix
     * @param length length of ip prefix
     * @return object of this class
     */
    public static BgpFsDestinationPrefix of(final IpPrefix ipPrefix, final byte length) {
        return new BgpFsDestinationPrefix(length, ipPrefix);
    }

    @Override
    public int compareTo(Object o) {
        if (this.equals(o)) {
            return 0;
        }

        if (o instanceof BgpFsDestinationPrefix) {
            BgpFsDestinationPrefix that = (BgpFsDestinationPrefix) o;

            if (this.ipPrefix().prefixLength() == that.ipPrefix().prefixLength()) {
                ByteBuffer value1 = ByteBuffer.wrap(this.ipPrefix.address().toOctets());
                ByteBuffer value2 = ByteBuffer.wrap(that.ipPrefix.address().toOctets());
                return value1.compareTo(value2);
            }

            if (this.ipPrefix().prefixLength() > that.ipPrefix().prefixLength()) {
                return 1;
            } else if (this.ipPrefix().prefixLength() < that.ipPrefix().prefixLength()) {
                return -1;
            }
        }
        return 1;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(getClass())
                .add("FLOW_SPEC_TYPE", FLOW_SPEC_TYPE)
                .add("length", length)
                .add("ipPrefix", ipPrefix).toString();
    }
}
