/*
 * Copyright 2015-present Open Networking Foundation
 *
 * 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.BgpErrorType;
import org.onosproject.bgpio.types.BgpValueType;
import org.onosproject.bgpio.types.IPReachabilityInformationTlv;
import org.onosproject.bgpio.types.OspfRouteTypeTlv;
import org.onosproject.bgpio.types.attr.BgpAttrNodeMultiTopologyId;
import org.onosproject.bgpio.util.UnSupportedAttribute;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.MoreObjects;

/**
 * Provides Implementation of Local node descriptors and prefix descriptors.
 */
public class BgpPrefixLSIdentifier implements Comparable<Object> {

    private static final Logger log = LoggerFactory.getLogger(BgpPrefixLSIdentifier.class);
    public static final int TYPE_AND_LEN = 4;
    private NodeDescriptors localNodeDescriptors;
    private List<BgpValueType> prefixDescriptor;

    /**
     * Resets parameters.
     */
    public BgpPrefixLSIdentifier() {
        this.localNodeDescriptors = null;
        this.prefixDescriptor = null;
        log.debug("Parameters are reset");
    }

    /**
     * Constructor to initialize parameters.
     *
     * @param localNodeDescriptors Local node descriptors
     * @param prefixDescriptor Prefix Descriptors
     */
    public BgpPrefixLSIdentifier(NodeDescriptors localNodeDescriptors, List<BgpValueType> prefixDescriptor) {
        this.localNodeDescriptors = localNodeDescriptors;
        this.prefixDescriptor = prefixDescriptor;
    }

    /**
     * Reads the channel buffer and parses Prefix Identifier.
     *
     * @param cb ChannelBuffer
     * @param protocolId protocol ID
     * @return object of this class
     * @throws BgpParseException while parsing Prefix Identifier
     */
    public static BgpPrefixLSIdentifier parsePrefixIdendifier(ChannelBuffer cb, byte protocolId)
            throws BgpParseException {
        log.debug("Parse local node descriptor");
        NodeDescriptors localNodeDescriptors = new NodeDescriptors();
        localNodeDescriptors = parseLocalNodeDescriptors(cb, protocolId);

        log.debug("MultiTopologyId TLV cannot repeat more than once");
        List<BgpValueType> prefixDescriptor = new LinkedList<>();
        prefixDescriptor = parsePrefixDescriptors(cb);
        return new BgpPrefixLSIdentifier(localNodeDescriptors, prefixDescriptor);
    }

    /**
     * Parse local node descriptors.
     *
     * @param cb ChannelBuffer
     * @param protocolId protocol identifier
     * @return LocalNodeDescriptors
     * @throws BgpParseException while parsing local node descriptors
     */
    public static NodeDescriptors parseLocalNodeDescriptors(ChannelBuffer cb, byte protocolId)
                                                                 throws BgpParseException {
        ChannelBuffer tempBuf = cb.copy();
        short type = cb.readShort();
        short length = cb.readShort();
        if (cb.readableBytes() < length) {
            //length + 4 implies data contains type, length and value
            throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR,
                    tempBuf.readBytes(cb.readableBytes() + TYPE_AND_LEN));
        }
        NodeDescriptors localNodeDescriptors = new NodeDescriptors();
        ChannelBuffer tempCb = cb.readBytes(length);

        if (type == NodeDescriptors.LOCAL_NODE_DES_TYPE) {
            localNodeDescriptors = NodeDescriptors.read(tempCb, length, type, protocolId);
        } else {
            throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR,
                                           BgpErrorType.MALFORMED_ATTRIBUTE_LIST, null);
        }
        return localNodeDescriptors;
    }

    /**
     * Parse list of prefix descriptors.
     *
     * @param cb ChannelBuffer
     * @return list of prefix descriptors
     * @throws BgpParseException while parsing list of prefix descriptors
     */
    public static List<BgpValueType> parsePrefixDescriptors(ChannelBuffer cb) throws BgpParseException {
        LinkedList<BgpValueType> prefixDescriptor = new LinkedList<>();
        BgpValueType tlv = null;
        boolean isIpReachInfo = false;
        ChannelBuffer tempCb;
        int count = 0;

        while (cb.readableBytes() > 0) {
            ChannelBuffer tempBuf = cb.copy();
            short type = cb.readShort();
            short length = cb.readShort();
            if (cb.readableBytes() < length) {
                //length + 4 implies data contains type, length and value
                throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR,
                        tempBuf.readBytes(cb.readableBytes() + TYPE_AND_LEN));
            }
            tempCb = cb.readBytes(length);
            switch (type) {
            case OspfRouteTypeTlv.TYPE:
                tlv = OspfRouteTypeTlv.read(tempCb);
                break;
            case IPReachabilityInformationTlv.TYPE:
                tlv = IPReachabilityInformationTlv.read(tempCb, length);
                isIpReachInfo = true;
                break;
            case BgpAttrNodeMultiTopologyId.ATTRNODE_MULTITOPOLOGY:
                tlv = BgpAttrNodeMultiTopologyId.read(tempCb);
                count = count + 1;
                if (count > 1) {
                    //length + 4 implies data contains type, length and value
                    throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR,
                           BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR, tempBuf.readBytes(length + TYPE_AND_LEN));
                }
                break;
            default:
                UnSupportedAttribute.skipBytes(tempCb, length);
            }
            prefixDescriptor.add(tlv);
        }

        if (!isIpReachInfo) {
            throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR,
                    null);
        }
        return prefixDescriptor;
    }

    /**
     * Returns local node descriptors.
     *
     * @return local node descriptors
     */
    public NodeDescriptors getLocalNodeDescriptors() {
        return this.localNodeDescriptors;
    }

    /**
     * Returns Prefix descriptors.
     *
     * @return Prefix descriptors
     */
    public List<BgpValueType> getPrefixdescriptor() {
        return this.prefixDescriptor;
    }

    @Override
    public int hashCode() {
        return Objects.hash(prefixDescriptor.hashCode(), localNodeDescriptors);
    }

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

        if (obj instanceof BgpPrefixLSIdentifier) {
            int countObjSubTlv = 0;
            int countOtherSubTlv = 0;
            boolean isCommonSubTlv = true;
            BgpPrefixLSIdentifier other = (BgpPrefixLSIdentifier) obj;

            Iterator<BgpValueType> objListIterator = other.prefixDescriptor.iterator();
            countOtherSubTlv = other.prefixDescriptor.size();
            countObjSubTlv = prefixDescriptor.size();
            if (countObjSubTlv != countOtherSubTlv) {
                return false;
            } else {
                while (objListIterator.hasNext() && isCommonSubTlv) {
                    BgpValueType subTlv = objListIterator.next();
                    if (prefixDescriptor.contains(subTlv) && other.prefixDescriptor.contains(subTlv)) {
                        isCommonSubTlv = Objects.equals(prefixDescriptor.get(prefixDescriptor.indexOf(subTlv)),
                                         other.prefixDescriptor.get(other.prefixDescriptor.indexOf(subTlv)));
                    } else {
                        isCommonSubTlv = false;
                    }
                }
                return isCommonSubTlv && Objects.equals(this.localNodeDescriptors, other.localNodeDescriptors);
            }
        }
        return false;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(getClass())
                .add("localNodeDescriptors", localNodeDescriptors)
                .add("prefixDescriptor", prefixDescriptor)
                .toString();
    }

    @Override
    public int compareTo(Object o) {
        if (this.equals(o)) {
            return 0;
        }
        int result = this.localNodeDescriptors.compareTo(((BgpPrefixLSIdentifier) o).localNodeDescriptors);
        boolean tlvFound = false;
        if (result != 0) {
            return result;
        } else {
            int countOtherSubTlv = ((BgpPrefixLSIdentifier) o).prefixDescriptor.size();
            int countObjSubTlv = prefixDescriptor.size();
            if (countOtherSubTlv != countObjSubTlv) {
                if (countOtherSubTlv > countObjSubTlv) {
                    return 1;
                } else {
                    return -1;
                }
            }

            ListIterator<BgpValueType> listIterator = prefixDescriptor.listIterator();
            while (listIterator.hasNext()) {
                BgpValueType tlv1 = listIterator.next();
                for (BgpValueType tlv : ((BgpPrefixLSIdentifier) o).prefixDescriptor) {
                    if (tlv.getType() == tlv1.getType()) {
                        result = prefixDescriptor.get(prefixDescriptor.indexOf(tlv1)).compareTo(
                                ((BgpPrefixLSIdentifier) o).prefixDescriptor
                                        .get(((BgpPrefixLSIdentifier) o).prefixDescriptor.indexOf(tlv)));
                        if (result != 0) {
                            return result;
                        }
                        tlvFound = true;
                        break;
                    }
                }
                if (!tlvFound) {
                    return 1;
                }
            }
        }
        return 0;
    }
}
