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

import java.util.Objects;

import org.jboss.netty.buffer.ChannelBuffer;
import org.onosproject.bgpio.exceptions.BgpParseException;
import org.onosproject.bgpio.types.BgpErrorType;
import org.onosproject.bgpio.types.BgpValueType;
import org.onosproject.bgpio.util.Validation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.MoreObjects;

/**
 * Implements BGP prefix IGP Flag attribute.
 */
public final class BgpPrefixAttrIgpFlags implements BgpValueType {

    protected static final Logger log = LoggerFactory
            .getLogger(BgpPrefixAttrIgpFlags.class);

    public static final int ATTR_PREFIX_FLAGBIT = 1152;
    public static final int ATTR_PREFIX_FLAG_LEN = 1;

    public static final byte FIRST_BIT = (byte) 0x80;
    public static final byte SECOND_BIT = 0x40;
    public static final byte THIRD_BIT = 0x20;
    public static final byte FOURTH_BIT = 0x01;

    /* Prefix IGP flag bit TLV */
    private final boolean bisisUpDownBit;
    private final boolean bOspfNoUnicastBit;
    private final boolean bOspfLclAddrBit;
    private final boolean bOspfNSSABit;

    /**
     * Constructor to initialize the value.
     *
     * @param bisisUpDownBit IS-IS Up/Down Bit
     * @param bOspfNoUnicastBit OSPF no unicast Bit
     * @param bOspfLclAddrBit OSPF local address Bit
     * @param bOspfNSSABit OSPF propagate NSSA Bit
     */
    public BgpPrefixAttrIgpFlags(boolean bisisUpDownBit,
                          boolean bOspfNoUnicastBit,
                          boolean bOspfLclAddrBit, boolean bOspfNSSABit) {
        this.bisisUpDownBit = bisisUpDownBit;
        this.bOspfNoUnicastBit = bOspfNoUnicastBit;
        this.bOspfLclAddrBit = bOspfLclAddrBit;
        this.bOspfNSSABit = bOspfNSSABit;
    }

    /**
     * Returns object of this class with specified values.
     *
     * @param bisisUpDownBit IS-IS Up/Down Bit
     * @param bOspfNoUnicastBit OSPF no unicast Bit
     * @param bOspfLclAddrBit OSPF local address Bit
     * @param bOspfNSSABit OSPF propagate NSSA Bit
     * @return object of BgpPrefixAttrIGPFlags
     */
    public static BgpPrefixAttrIgpFlags of(final boolean bisisUpDownBit,
                                           final boolean bOspfNoUnicastBit,
                                           final boolean bOspfLclAddrBit,
                                           final boolean bOspfNSSABit) {
        return new BgpPrefixAttrIgpFlags(bisisUpDownBit, bOspfNoUnicastBit,
                                         bOspfLclAddrBit, bOspfNSSABit);
    }

    /**
     * Reads the IGP Flags.
     *
     * @param cb ChannelBuffer
     * @return object of BgpPrefixAttrIGPFlags
     * @throws BgpParseException while parsing BgpPrefixAttrIGPFlags
     */
    public static BgpPrefixAttrIgpFlags read(ChannelBuffer cb)
            throws BgpParseException {
        boolean bisisUpDownBit = false;
        boolean bOspfNoUnicastBit = false;
        boolean bOspfLclAddrBit = false;
        boolean bOspfNSSABit = false;

        short lsAttrLength = cb.readShort();

        if ((lsAttrLength != ATTR_PREFIX_FLAG_LEN)
                || (cb.readableBytes() < lsAttrLength)) {
            Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
                                   BgpErrorType.ATTRIBUTE_LENGTH_ERROR,
                                   lsAttrLength);
        }

        byte nodeFlagBits = cb.readByte();

        bisisUpDownBit = ((nodeFlagBits & FIRST_BIT) == FIRST_BIT);
        bOspfNoUnicastBit = ((nodeFlagBits & SECOND_BIT) == SECOND_BIT);
        bOspfLclAddrBit = ((nodeFlagBits & THIRD_BIT) == THIRD_BIT);
        bOspfNSSABit = ((nodeFlagBits & FOURTH_BIT) == FOURTH_BIT);

        return BgpPrefixAttrIgpFlags.of(bisisUpDownBit, bOspfNoUnicastBit,
                                        bOspfLclAddrBit, bOspfNSSABit);
    }

    /**
     * Returns the IS-IS Up/Down Bit set or not.
     *
     * @return IS-IS Up/Down Bit set or not
     */
    public boolean isisUpDownBit() {
        return bisisUpDownBit;
    }

    /**
     * Returns the OSPF no unicast Bit set or not.
     *
     * @return OSPF no unicast Bit set or not
     */
    public boolean ospfNoUnicastBit() {
        return bOspfNoUnicastBit;
    }

    /**
     * Returns the OSPF local address Bit set or not.
     *
     * @return OSPF local address Bit set or not
     */
    public boolean ospfLclAddrBit() {
        return bOspfLclAddrBit;
    }

    /**
     * Returns the OSPF propagate NSSA Bit set or not.
     *
     * @return OSPF propagate NSSA Bit set or not
     */
    public boolean ospfNSSABit() {
        return bOspfNSSABit;
    }

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

    @Override
    public int write(ChannelBuffer cb) {
        // TODO This will be implemented in the next version
        return 0;
    }

    @Override
    public int hashCode() {
        return Objects.hash(bisisUpDownBit, bOspfNoUnicastBit, bOspfLclAddrBit,
                            bOspfNSSABit);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }

        if (obj instanceof BgpPrefixAttrIgpFlags) {
            BgpPrefixAttrIgpFlags other = (BgpPrefixAttrIgpFlags) obj;
            return Objects.equals(bisisUpDownBit, other.bisisUpDownBit)
                    && Objects.equals(bOspfNoUnicastBit,
                                      other.bOspfNoUnicastBit)
                                      && Objects.equals(bOspfLclAddrBit, other.bOspfLclAddrBit)
                                      && Objects.equals(bOspfNSSABit, other.bOspfNSSABit);
        }
        return false;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(getClass())
                .add("bisisUpDownBit", bisisUpDownBit)
                .add("bOspfNoUnicastBit", bOspfNoUnicastBit)
                .add("bOspfLclAddrBit", bOspfLclAddrBit)
                .add("bOspfNSSABit", bOspfNSSABit).toString();
    }

    @Override
    public int compareTo(Object o) {
        // TODO Auto-generated method stub
        return 0;
    }
}
