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