/*
 * 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 BgpFsSourcePrefix implements BgpValueType {

    public static final byte FLOW_SPEC_TYPE = Constants.BGP_FLOWSPEC_SRC_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 BgpFsSourcePrefix(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 this.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 BgpFsSourcePrefix) {
            BgpFsSourcePrefix other = (BgpFsSourcePrefix) obj;
            return Objects.equals(this.ipPrefix, other.ipPrefix) && Objects.equals(this.length, other.length);
        }
        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 source prefix
     * @throws BgpParseException while parsing BgpFsSourcePrefix
     */
    public static BgpFsSourcePrefix 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 BgpFsSourcePrefix((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 BgpFsSourcePrefix((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 BgpFsSourcePrefix of(final IpPrefix ipPrefix, final byte length) {
        return new BgpFsSourcePrefix(length, ipPrefix);
    }

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

        if (o instanceof BgpFsSourcePrefix) {
            BgpFsSourcePrefix that = (BgpFsSourcePrefix) 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();
    }
}
