/*
 * 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;

import java.util.LinkedList;
import java.util.List;

import org.jboss.netty.buffer.ChannelBuffer;
import org.onosproject.bgpio.exceptions.BgpParseException;
import org.onosproject.bgpio.types.attr.BgpAttrNodeFlagBitTlv;
import org.onosproject.bgpio.types.attr.BgpAttrNodeIsIsAreaId;
import org.onosproject.bgpio.types.attr.BgpAttrNodeMultiTopologyId;
import org.onosproject.bgpio.types.attr.BgpAttrNodeName;
import org.onosproject.bgpio.types.attr.BgpAttrOpaqueNode;
import org.onosproject.bgpio.types.attr.BgpAttrRouterIdV4;
import org.onosproject.bgpio.types.attr.BgpAttrRouterIdV6;
import org.onosproject.bgpio.types.attr.BgpLinkAttrIgpMetric;
import org.onosproject.bgpio.types.attr.BgpLinkAttrIsIsAdminstGrp;
import org.onosproject.bgpio.types.attr.BgpLinkAttrMplsProtocolMask;
import org.onosproject.bgpio.types.attr.BgpLinkAttrMaxLinkBandwidth;
import org.onosproject.bgpio.types.attr.BgpLinkAttrName;
import org.onosproject.bgpio.types.attr.BgpLinkAttrOpaqLnkAttrib;
import org.onosproject.bgpio.types.attr.BgpLinkAttrProtectionType;
import org.onosproject.bgpio.types.attr.BgpLinkAttrSrlg;
import org.onosproject.bgpio.types.attr.BgpLinkAttrTeDefaultMetric;
import org.onosproject.bgpio.types.attr.BgpLinkAttrUnRsrvdLinkBandwidth;
import org.onosproject.bgpio.types.attr.BgpPrefixAttrExtRouteTag;
import org.onosproject.bgpio.types.attr.BgpPrefixAttrIgpFlags;
import org.onosproject.bgpio.types.attr.BgpPrefixAttrMetric;
import org.onosproject.bgpio.types.attr.BgpPrefixAttrOspfFwdAddr;
import org.onosproject.bgpio.types.attr.BgpPrefixAttrOpaqueData;
import org.onosproject.bgpio.types.attr.BgpPrefixAttrRouteTag;
import org.onosproject.bgpio.util.Validation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.MoreObjects;

/**
 * Implements BGP Link state attribute.
 */
public class LinkStateAttributes implements BgpValueType {

    protected static final Logger log = LoggerFactory
            .getLogger(LinkStateAttributes.class);

    /* Node Attributes */
    public static final short ATTR_NODE_MT_TOPOLOGY_ID = 263;
    public static final short ATTR_NODE_FLAG_BITS = 1024;
    public static final short ATTR_NODE_OPAQUE_NODE = 1025;
    public static final short ATTR_NODE_NAME = 1026;
    public static final short ATTR_NODE_ISIS_AREA_ID = 1027;
    public static final short ATTR_NODE_IPV4_LOCAL_ROUTER_ID = 1028;
    public static final short ATTR_NODE_IPV6_LOCAL_ROUTER_ID = 1029;

    /* Link Attributes */
    public static final short ATTR_LINK_IPV4_REMOTE_ROUTER_ID = 1030;
    public static final short ATTR_LINK_IPV6_REMOTE_ROUTER_ID = 1031;
    public static final short ATTR_LINK_ADMINISTRATIVE_GRPS = 1088;
    public static final short ATTR_LINK_MAX_BANDWIDTH = 1089;
    public static final short ATTR_LINK_MAX_RES_BANDWIDTH = 1090;
    public static final short ATTR_LINK_UNRES_BANDWIDTH = 1091;
    public static final short ATTR_LINK_TE_DEFAULT_METRIC = 1092;
    public static final short ATTR_LINK_PROTECTION_TYPE = 1093;
    public static final short ATTR_LINK_MPLS_PROTOCOL_MASK = 1094;
    public static final short ATTR_LINK_IGP_METRIC = 1095;
    public static final short ATTR_LINK_SHR_RISK_GRP = 1096;
    public static final short ATTR_LINK_OPAQUE_ATTR = 1097;
    public static final short ATTR_LINK_NAME_ATTR = 1098;

    /* Prefix Attributes */
    public static final short ATTR_PREFIX_IGP_FLAG = 1152;
    public static final short ATTR_PREFIX_ROUTE_TAG = 1153;
    public static final short ATTR_PREFIX_EXTENDED_TAG = 1154;
    public static final short ATTR_PREFIX_METRIC = 1155;
    public static final short ATTR_PREFIX_OSPF_FWD_ADDR = 1156;
    public static final short ATTR_PREFIX_OPAQUE_ATTR = 1157;

    public static final byte LINKSTATE_ATTRIB_TYPE = 50;
    public static final byte TYPE_AND_LEN = 4;
    private boolean isLinkStateAttribute = false;
    private List<BgpValueType> linkStateAttribList;

    /**
     * Constructor to reset parameters.
     */
    LinkStateAttributes() {
        this.linkStateAttribList = null;
    }

    /**
     * Constructor to initialize parameters.
     *
     * @param linkStateAttribList Linked list of Link, Node and Prefix TLVs
     */
    LinkStateAttributes(List<BgpValueType> linkStateAttribList) {
        this.linkStateAttribList = linkStateAttribList;
        this.isLinkStateAttribute = true;
    }

    /**
     * Returns linked list of Link, Node and Prefix TLVs.
     *
     * @return linked list of Link, Node and Prefix TLVs
     */
    public List<BgpValueType> linkStateAttributes() {
        return this.linkStateAttribList;
    }

    /**
     * Returns if the Link state attributes are set or not.
     *
     * @return a boolean value to to check if the LS attributes are set or not
     */
    public boolean isLinkStateAttributeSet() {
        return this.isLinkStateAttribute;
    }

    /**
     * Reads the Link state attribute TLVs.
     *
     * @param cb ChannelBuffer
     * @return constructor of LinkStateAttributes
     * @throws BgpParseException while parsing link state attributes
     */
    public static LinkStateAttributes read(ChannelBuffer cb)
            throws BgpParseException {

        ChannelBuffer tempBuf = cb;
        Validation parseFlags = Validation.parseAttributeHeader(cb);
        int len = parseFlags.isShort() ? parseFlags.getLength() + TYPE_AND_LEN
                                      : parseFlags.getLength() + 3;

        ChannelBuffer data = tempBuf.readBytes(len);
        if (!parseFlags.getFirstBit() || parseFlags.getSecondBit()
                || parseFlags.getThirdBit()) {
            throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR,
                                        BgpErrorType.ATTRIBUTE_FLAGS_ERROR,
                                        data);
        }

        if (cb.readableBytes() < parseFlags.getLength()) {
            Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
                                   BgpErrorType.BAD_MESSAGE_LENGTH,
                                   parseFlags.getLength());
        }

        BgpValueType bgpLSAttrib = null;
        LinkedList<BgpValueType> linkStateAttribList;
        linkStateAttribList = new LinkedList<BgpValueType>();
        ChannelBuffer tempCb = cb.readBytes(parseFlags.getLength());
        while (tempCb.readableBytes() > 0) {
            short tlvCodePoint = tempCb.readShort();
            switch (tlvCodePoint) {

            /********* 7 NODE ATTRIBUTES ********/
            case ATTR_NODE_MT_TOPOLOGY_ID: /* 263 Multi-Topology Identifier*/
                bgpLSAttrib = BgpAttrNodeMultiTopologyId.read(tempCb);
                break;

            case ATTR_NODE_FLAG_BITS: /*Node flag bit TLV*/
                bgpLSAttrib = BgpAttrNodeFlagBitTlv.read(tempCb);
                break;

            case ATTR_NODE_OPAQUE_NODE: /*Opaque Node Attribute*/
                bgpLSAttrib = BgpAttrOpaqueNode.read(tempCb);
                break;

            case ATTR_NODE_NAME: /*Node Name*/
                bgpLSAttrib = BgpAttrNodeName.read(tempCb);
                break;

            case ATTR_NODE_ISIS_AREA_ID: /*IS-IS Area Identifier TLV*/
                bgpLSAttrib = BgpAttrNodeIsIsAreaId.read(tempCb);
                break;

            case ATTR_NODE_IPV4_LOCAL_ROUTER_ID: /*IPv4 Router-ID of Local Node*/
                bgpLSAttrib = BgpAttrRouterIdV4.read(tempCb, (short) ATTR_NODE_IPV4_LOCAL_ROUTER_ID);
                break;

            case ATTR_NODE_IPV6_LOCAL_ROUTER_ID: /*IPv6 Router-ID of Local Node*/
                bgpLSAttrib = BgpAttrRouterIdV6.read(tempCb, (short) ATTR_NODE_IPV6_LOCAL_ROUTER_ID);
                break;

            /********* 15 LINK ATTRIBUTES ********/

            case ATTR_LINK_IPV4_REMOTE_ROUTER_ID: /*IPv4 Router-ID of Remote Node*/
                bgpLSAttrib = BgpAttrRouterIdV4.read(tempCb, (short) 1030);
                break;

            case ATTR_LINK_IPV6_REMOTE_ROUTER_ID: /*IPv6 Router-ID of Remote Node*/
                bgpLSAttrib = BgpAttrRouterIdV6.read(tempCb, (short) 1031);
                break;

            case ATTR_LINK_ADMINISTRATIVE_GRPS: /*ISIS Administrative group STLV 3*/
                bgpLSAttrib = BgpLinkAttrIsIsAdminstGrp.read(tempCb);
                break;

            case ATTR_LINK_MAX_BANDWIDTH: /*Maximum link bandwidth*/
                bgpLSAttrib = BgpLinkAttrMaxLinkBandwidth.read(tempCb,
                                                               (short) 1089);
                break;

            case ATTR_LINK_MAX_RES_BANDWIDTH: /* Maximum Reservable link bandwidth */
                bgpLSAttrib = BgpLinkAttrMaxLinkBandwidth.read(tempCb,
                                                               (short) 1090);
                break;

            case ATTR_LINK_UNRES_BANDWIDTH: /* UnReserved link bandwidth */
                bgpLSAttrib = BgpLinkAttrUnRsrvdLinkBandwidth
                        .read(tempCb, (short) 1091);
                break;

            case ATTR_LINK_TE_DEFAULT_METRIC: /* TE Default Metric */
                bgpLSAttrib = BgpLinkAttrTeDefaultMetric.read(tempCb);
                break;

            case ATTR_LINK_PROTECTION_TYPE:/* Link Protection type */
                bgpLSAttrib = BgpLinkAttrProtectionType.read(tempCb);
                break;

            case ATTR_LINK_MPLS_PROTOCOL_MASK: /* MPLS Protocol Mask */
                bgpLSAttrib = BgpLinkAttrMplsProtocolMask.read(tempCb); // 2
                break;

            case ATTR_LINK_IGP_METRIC: /* IGP Metric */
                bgpLSAttrib = BgpLinkAttrIgpMetric.read(tempCb); // 2
                break;

            case ATTR_LINK_SHR_RISK_GRP: /* Shared Risk Link Group */
                bgpLSAttrib = BgpLinkAttrSrlg.read(tempCb); // 3
                break;

            case ATTR_LINK_OPAQUE_ATTR: /* Opaque link attribute */
                bgpLSAttrib = BgpLinkAttrOpaqLnkAttrib.read(tempCb);
                break;

            case ATTR_LINK_NAME_ATTR: /* Link Name attribute */
                bgpLSAttrib = BgpLinkAttrName.read(tempCb);
                break;

            /********* 6 PREFIX ATTRIBUTES ********/

            case ATTR_PREFIX_IGP_FLAG: /* IGP Flags */
                bgpLSAttrib = BgpPrefixAttrIgpFlags.read(tempCb);
                break;

            case ATTR_PREFIX_ROUTE_TAG: /* Route Tag */
                bgpLSAttrib = BgpPrefixAttrRouteTag.read(tempCb);
                break;

            case ATTR_PREFIX_EXTENDED_TAG: /* Extended Tag */
                bgpLSAttrib = BgpPrefixAttrExtRouteTag.read(tempCb);
                break;

            case ATTR_PREFIX_METRIC: /* Prefix Metric */
                bgpLSAttrib = BgpPrefixAttrMetric.read(tempCb);
                break;

            case ATTR_PREFIX_OSPF_FWD_ADDR: /* OSPF Forwarding Address */
                bgpLSAttrib = BgpPrefixAttrOspfFwdAddr.read(tempCb);
                break;

            case ATTR_PREFIX_OPAQUE_ATTR: /* Opaque Prefix Attribute */
                bgpLSAttrib = BgpPrefixAttrOpaqueData.read(tempCb);
                break;

            default:
                throw new BgpParseException(
                                            "The Bgp-LS Attribute is not supported : "
                                                    + tlvCodePoint);
            }

            linkStateAttribList.add(bgpLSAttrib);
        }
        return new LinkStateAttributes(linkStateAttribList);
    }

    @Override
    public short getType() {
        return LINKSTATE_ATTRIB_TYPE;
    }

    @Override
    public int write(ChannelBuffer cb) {
        // TODO This will be implemented in the next version
        return 0;
    }

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