/*
 * 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.protocol.linkstate;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Objects;

import org.jboss.netty.buffer.ChannelBuffer;
import org.onosproject.bgpio.exceptions.BgpParseException;
import org.onosproject.bgpio.types.AreaIDTlv;
import org.onosproject.bgpio.types.AutonomousSystemTlv;
import org.onosproject.bgpio.types.BgpErrorType;
import org.onosproject.bgpio.types.BgpLSIdentifierTlv;
import org.onosproject.bgpio.types.BgpValueType;
import org.onosproject.bgpio.types.IsIsNonPseudonode;
import org.onosproject.bgpio.types.IsIsPseudonode;
import org.onosproject.bgpio.types.OSPFNonPseudonode;
import org.onosproject.bgpio.types.OSPFPseudonode;
import org.onosproject.bgpio.util.UnSupportedAttribute;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.MoreObjects;

/**
 * Provides Local and Remote NodeDescriptors which contains Node Descriptor Sub-TLVs.
 */
public class NodeDescriptors {

    /*
     *Reference :draft-ietf-idr-ls-distribution-11
          0                   1                   2                   3
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         |              Type             |             Length            |
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         |                                                               |
         //              Node Descriptor Sub-TLVs (variable)            //
         |                                                               |
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                   Figure : Local or Remote Node Descriptors TLV format
     */

    private static final Logger log = LoggerFactory.getLogger(NodeDescriptors.class);

    public static final short LOCAL_NODE_DES_TYPE = 256;
    public static final short REMOTE_NODE_DES_TYPE = 257;
    public static final short IGP_ROUTERID_TYPE = 515;
    public static final short IS_IS_LEVEL_1_PROTOCOL_ID = 1;
    public static final short IS_IS_LEVEL_2_PROTOCOL_ID = 2;
    public static final short OSPF_V2_PROTOCOL_ID = 3;
    public static final short OSPF_V3_PROTOCOL_ID = 6;
    public static final int TYPE_AND_LEN = 4;
    public static final int ISISNONPSEUDONODE_LEN = 6;
    public static final int ISISPSEUDONODE_LEN = 7;
    public static final int OSPFNONPSEUDONODE_LEN = 4;
    public static final int OSPFPSEUDONODE_LEN = 8;
    private List<BgpValueType> subTlvs;
    private short deslength;
    private short desType;

    /**
     * Resets parameters.
     */
    public NodeDescriptors() {
        this.subTlvs = null;
        this.deslength = 0;
        this.desType = 0;
    }

    /**
     * Constructor to initialize parameters.
     *
     * @param subTlvs list of subTlvs
     * @param deslength Descriptors length
     * @param desType local node descriptor or remote node descriptor type
     */
    public NodeDescriptors(List<BgpValueType> subTlvs, short deslength, short desType) {
        this.subTlvs = subTlvs;
        this.deslength = deslength;
        this.desType = desType;
    }

    /**
     * Returns list of subTlvs.
     *
     * @return subTlvs list of subTlvs
     */
    public List<BgpValueType> getSubTlvs() {
        return subTlvs;
    }

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

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

        if (obj instanceof NodeDescriptors) {
            int countObjSubTlv = 0;
            int countOtherSubTlv = 0;
            boolean isCommonSubTlv = true;
            NodeDescriptors other = (NodeDescriptors) obj;
            Iterator<BgpValueType> objListIterator = other.subTlvs.iterator();
            countOtherSubTlv = other.subTlvs.size();
            countObjSubTlv = subTlvs.size();
            if (countObjSubTlv != countOtherSubTlv) {
                return false;
            } else {
                while (objListIterator.hasNext() && isCommonSubTlv) {
                    BgpValueType subTlv = objListIterator.next();
                    if (subTlvs.contains(subTlv) && other.subTlvs.contains(subTlv)) {
                        isCommonSubTlv = Objects.equals(subTlvs.get(subTlvs.indexOf(subTlv)),
                                         other.subTlvs.get(other.subTlvs.indexOf(subTlv)));
                    } else {
                        isCommonSubTlv = false;
                    }
                }
                return isCommonSubTlv;
            }
        }
        return false;
    }

    /**
     * Reads node descriptors Sub-TLVs.
     *
     * @param cb ChannelBuffer
     * @param desLength node descriptor length
     * @param desType local node descriptor or remote node descriptor type
     * @param protocolId protocol ID
     * @return object of NodeDescriptors
     * @throws BgpParseException while parsing node descriptors
     */
    public static NodeDescriptors read(ChannelBuffer cb, short desLength, short desType, byte protocolId)
            throws BgpParseException {
        log.debug("Read NodeDescriptor");
        List<BgpValueType> subTlvs = new LinkedList<>();
        BgpValueType tlv = null;

        while (cb.readableBytes() > 0) {
            ChannelBuffer tempBuf = cb.copy();
            short type = cb.readShort();
            short length = cb.readShort();
            if (cb.readableBytes() < length) {
                throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR,
                        tempBuf.readBytes(cb.readableBytes() + TYPE_AND_LEN));
            }
            ChannelBuffer tempCb = cb.readBytes(length);
            switch (type) {
            case AutonomousSystemTlv.TYPE:
                tlv = AutonomousSystemTlv.read(tempCb);
                break;
            case BgpLSIdentifierTlv.TYPE:
                tlv = BgpLSIdentifierTlv.read(tempCb);
                break;
            case AreaIDTlv.TYPE:
                tlv = AreaIDTlv.read(tempCb);
                break;
            case IGP_ROUTERID_TYPE:
                if (protocolId == IS_IS_LEVEL_1_PROTOCOL_ID || protocolId == IS_IS_LEVEL_2_PROTOCOL_ID) {
                    boolean isNonPseudoNode = true;
                    if ((length == ISISPSEUDONODE_LEN) && (tempCb.getByte(ISISPSEUDONODE_LEN - 1) != 0)) {
                        isNonPseudoNode = false;
                    }
                    if (isNonPseudoNode) {
                        tlv = IsIsNonPseudonode.read(tempCb);
                    } else {
                        tlv = IsIsPseudonode.read(tempCb);
                    }
                } else if (protocolId == OSPF_V2_PROTOCOL_ID || protocolId == OSPF_V3_PROTOCOL_ID) {
                    if (length == OSPFNONPSEUDONODE_LEN) {
                        tlv = OSPFNonPseudonode.read(tempCb);
                    } else if (length == OSPFPSEUDONODE_LEN) {
                        tlv = OSPFPseudonode.read(tempCb);
                    }
                }
                break;
            default:
                UnSupportedAttribute.skipBytes(tempCb, length);
            }
            subTlvs.add(tlv);
        }
        return new NodeDescriptors(subTlvs, desLength, desType);
    }

    /**
     * Returns node descriptors length.
     *
     * @return node descriptors length
     */
    public short getLength() {
        return this.deslength;
    }

    /**
     * Returns node descriptors type.
     *
     * @return node descriptors type
     */
    public short getType() {
        return this.desType;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(getClass())
                .add("desType", desType)
                .add("deslength", deslength)
                .add("subTlvs", subTlvs)
                .toString();
    }

    /**
     * Compares this and o object.
     *
     * @param o object to be compared with this object
     * @return which object is greater
     */
    public int compareTo(Object o) {
        if (this.equals(o)) {
            return 0;
        }
        ListIterator<BgpValueType> listIterator = subTlvs.listIterator();
        int countOtherSubTlv = ((NodeDescriptors) o).subTlvs.size();
        int countObjSubTlv = subTlvs.size();
        boolean tlvFound = false;
        if (countOtherSubTlv != countObjSubTlv) {
            if (countOtherSubTlv > countObjSubTlv) {
                return 1;
            } else {
                return -1;
            }
        } else {
            while (listIterator.hasNext()) {
                BgpValueType tlv1 = listIterator.next();
                log.debug("NodeDescriptor compare subtlv's");
                for (BgpValueType tlv : ((NodeDescriptors) o).subTlvs) {
                    if (tlv.getType() == tlv1.getType()) {
                        int result = subTlvs.get(subTlvs.indexOf(tlv1)).compareTo(
                                ((NodeDescriptors) o).subTlvs.get(((NodeDescriptors) o).subTlvs.indexOf(tlv)));
                        if (result != 0) {
                            return result;
                        }
                        tlvFound = true;
                        break;
                    }
                }
                if (!tlvFound) {
                    return 1;
                }
            }
        }
        return 0;
    }
}
