/*
 * 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.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> {

    protected 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;
    }

    /**
     * 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 {
        //Parse Local Node descriptor
        NodeDescriptors localNodeDescriptors = new NodeDescriptors();
        localNodeDescriptors = parseLocalNodeDescriptors(cb, protocolId);

        //Parse Prefix descriptor
        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);
        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();
            ListIterator<BgpValueType> listIteratorOther = ((BgpPrefixLSIdentifier) o).prefixDescriptor.listIterator();
            while (listIterator.hasNext()) {
                BgpValueType tlv = listIterator.next();
                BgpValueType tlv1 = listIteratorOther.next();
                if (prefixDescriptor.contains(tlv) && ((BgpPrefixLSIdentifier) o).prefixDescriptor.contains(tlv1)) {
                    int res = prefixDescriptor.get(prefixDescriptor.indexOf(tlv)).compareTo(
                            ((BgpPrefixLSIdentifier) o).prefixDescriptor
                                    .get(((BgpPrefixLSIdentifier) o).prefixDescriptor.indexOf(tlv1)));
                    if (res != 0) {
                        return res;
                    }
                }
            }
        }
        return 0;
    }
}
