/*
 * 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.IPv4AddressTlv;
import org.onosproject.bgpio.types.IPv6AddressTlv;
import org.onosproject.bgpio.types.LinkLocalRemoteIdentifiersTlv;
import org.onosproject.bgpio.types.attr.BgpAttrNodeMultiTopologyId;
import org.onosproject.bgpio.util.Constants;
import org.onosproject.bgpio.util.UnSupportedAttribute;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;

/**
 * Implementation of local node descriptors, remote node descriptors and link descriptors.
 */
public class BgpLinkLSIdentifier implements Comparable<Object> {
    private static final Logger log = LoggerFactory.getLogger(BgpLinkLSIdentifier.class);
    public static final short IPV4_INTERFACE_ADDRESS_TYPE = 259;
    public static final short IPV4_NEIGHBOR_ADDRESS_TYPE = 260;
    public static final short IPV6_INTERFACE_ADDRESS_TYPE = 261;
    public static final short IPV6_NEIGHBOR_ADDRESS_TYPE = 262;

    private NodeDescriptors localNodeDescriptors;
    private NodeDescriptors remoteNodeDescriptors;
    private List<BgpValueType> linkDescriptor;

    /**
     * Initialize fields.
     */
    public BgpLinkLSIdentifier() {
        this.localNodeDescriptors = null;
        this.remoteNodeDescriptors = null;
        this.linkDescriptor = null;
    }

    /**
     * Constructors to initialize parameters.
     *
     * @param localNodeDescriptors local node descriptors
     * @param remoteNodeDescriptors remote node descriptors
     * @param linkDescriptor link descriptors
     */
    public BgpLinkLSIdentifier(NodeDescriptors localNodeDescriptors, NodeDescriptors remoteNodeDescriptors,
            LinkedList<BgpValueType> linkDescriptor) {
        this.localNodeDescriptors = Preconditions.checkNotNull(localNodeDescriptors);
        this.remoteNodeDescriptors = Preconditions.checkNotNull(remoteNodeDescriptors);
        this.linkDescriptor = Preconditions.checkNotNull(linkDescriptor);
    }

    /**
     * Reads channel buffer and parses link identifier.
     *
     * @param cb ChannelBuffer
     * @param protocolId in linkstate nlri
     * @return object of BGPLinkLSIdentifier
     * @throws BgpParseException while parsing link identifier
     */
    public static BgpLinkLSIdentifier parseLinkIdendifier(ChannelBuffer cb, byte protocolId) throws BgpParseException {
        //Parse local node descriptor
        NodeDescriptors localNodeDescriptors = new NodeDescriptors();
        localNodeDescriptors = parseNodeDescriptors(cb, NodeDescriptors.LOCAL_NODE_DES_TYPE, protocolId);

        //Parse remote node descriptor
        NodeDescriptors remoteNodeDescriptors = new NodeDescriptors();
        remoteNodeDescriptors = parseNodeDescriptors(cb, NodeDescriptors.REMOTE_NODE_DES_TYPE, protocolId);

        //Parse link descriptor
        LinkedList<BgpValueType> linkDescriptor = new LinkedList<>();
        linkDescriptor = parseLinkDescriptors(cb);
        return new BgpLinkLSIdentifier(localNodeDescriptors, remoteNodeDescriptors, linkDescriptor);
    }

    /**
     * Parses Local/Remote node descriptors.
     *
     * @param cb ChannelBuffer
     * @param desType descriptor type
     * @param protocolId protocol identifier
     * @return object of NodeDescriptors
     * @throws BgpParseException while parsing Local/Remote node descriptors
     */
    public static NodeDescriptors parseNodeDescriptors(ChannelBuffer cb, short desType, byte protocolId)
            throws BgpParseException {
        log.debug("parse Node descriptors");
        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() + Constants.TYPE_AND_LEN_AS_SHORT));
        }
        NodeDescriptors nodeIdentifier = new NodeDescriptors();
        ChannelBuffer tempCb = cb.readBytes(length);

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

    /**
     * Parses link descriptors.
     *
     * @param cb ChannelBuffer
     * @return list of link descriptors
     * @throws BgpParseException while parsing link descriptors
     */
    public static LinkedList<BgpValueType> parseLinkDescriptors(ChannelBuffer cb) throws BgpParseException {
        LinkedList<BgpValueType> linkDescriptor = new LinkedList<>();
        BgpValueType tlv = null;
        int count = 0;

        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() + Constants.TYPE_AND_LEN_AS_SHORT));
            }
            ChannelBuffer tempCb = cb.readBytes(length);
            switch (type) {
            case LinkLocalRemoteIdentifiersTlv.TYPE:
                tlv = LinkLocalRemoteIdentifiersTlv.read(tempCb);
                break;
            case IPV4_INTERFACE_ADDRESS_TYPE:
                tlv = IPv4AddressTlv.read(tempCb, IPV4_INTERFACE_ADDRESS_TYPE);
                break;
            case IPV4_NEIGHBOR_ADDRESS_TYPE:
                tlv = IPv4AddressTlv.read(tempCb, IPV4_NEIGHBOR_ADDRESS_TYPE);
                break;
            case IPV6_INTERFACE_ADDRESS_TYPE:
                tlv = IPv6AddressTlv.read(tempCb, IPV6_INTERFACE_ADDRESS_TYPE);
                break;
            case IPV6_NEIGHBOR_ADDRESS_TYPE:
                tlv = IPv6AddressTlv.read(tempCb, IPV6_NEIGHBOR_ADDRESS_TYPE);
                break;
            case BgpAttrNodeMultiTopologyId.ATTRNODE_MULTITOPOLOGY:
                tlv = BgpAttrNodeMultiTopologyId.read(tempCb);
                count = count++;
                //MultiTopologyId TLV cannot repeat more than once
                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
                                    + Constants.TYPE_AND_LEN_AS_SHORT));
                }
                break;
            default:
                UnSupportedAttribute.skipBytes(tempCb, length);
            }
            linkDescriptor.add(tlv);
        }
        return linkDescriptor;
    }

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

    /**
     * Returns remote node descriptors.
     *
     * @return remote node descriptors
     */
    public NodeDescriptors remoteNodeDescriptors() {
        return this.remoteNodeDescriptors;
    }

    /**
     * Returns link descriptors.
     *
     * @return link descriptors
     */
    public List<BgpValueType> linkDescriptors() {
        return this.linkDescriptor;
    }

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

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj instanceof BgpLinkLSIdentifier) {
            int countObjSubTlv = 0;
            int countOtherSubTlv = 0;
            boolean isCommonSubTlv = true;
            BgpLinkLSIdentifier other = (BgpLinkLSIdentifier) obj;
            Iterator<BgpValueType> objListIterator = other.linkDescriptor.iterator();
            countOtherSubTlv = other.linkDescriptor.size();
            countObjSubTlv = linkDescriptor.size();
            if (countObjSubTlv != countOtherSubTlv) {
                return false;
            } else {
                while (objListIterator.hasNext() && isCommonSubTlv) {
                    BgpValueType subTlv = objListIterator.next();
                    if (linkDescriptor.contains(subTlv) && other.linkDescriptor.contains(subTlv)) {
                        isCommonSubTlv = Objects.equals(linkDescriptor.get(linkDescriptor.indexOf(subTlv)),
                                         other.linkDescriptor.get(other.linkDescriptor.indexOf(subTlv)));
                    } else {
                        isCommonSubTlv = false;
                    }
                }
                return isCommonSubTlv && Objects.equals(this.localNodeDescriptors, other.localNodeDescriptors)
                        && Objects.equals(this.remoteNodeDescriptors, other.remoteNodeDescriptors);
            }
        }
        return false;
    }

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

    @Override
    public int compareTo(Object o) {
        if (this.equals(o)) {
            return 0;
        }
        int result = this.localNodeDescriptors.compareTo(((BgpLinkLSIdentifier) o).localNodeDescriptors);
        if (result != 0) {
            return result;
        } else if (this.remoteNodeDescriptors.compareTo(((BgpLinkLSIdentifier) o).remoteNodeDescriptors) != 0) {
            return this.remoteNodeDescriptors.compareTo(((BgpLinkLSIdentifier) o).remoteNodeDescriptors);
        } else {
            int countOtherSubTlv = ((BgpLinkLSIdentifier) o).linkDescriptor.size();
            int countObjSubTlv = linkDescriptor.size();
            if (countOtherSubTlv != countObjSubTlv) {
                if (countOtherSubTlv > countObjSubTlv) {
                    return 1;
                } else {
                    return -1;
                }
           }
            ListIterator<BgpValueType> listIterator = linkDescriptor.listIterator();
            ListIterator<BgpValueType> listIteratorOther = ((BgpLinkLSIdentifier) o).linkDescriptor.listIterator();
            while (listIterator.hasNext()) {
                BgpValueType tlv = listIterator.next();
                if (linkDescriptor.contains(tlv) && ((BgpLinkLSIdentifier) o).linkDescriptor.contains(tlv)) {
                    int res = linkDescriptor.get(linkDescriptor.indexOf(tlv)).compareTo(
                            ((BgpLinkLSIdentifier) o).linkDescriptor.get(((BgpLinkLSIdentifier) o).linkDescriptor
                                    .indexOf(tlv)));
                    if (res != 0) {
                        return res;
                    }
                } else {
                    return 1;
                }
            }
        }
        return 0;
    }
}
