/*
 * Copyright 2016 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.ospf.protocol.lsa.tlvtypes;

import com.google.common.base.MoreObjects;
import com.google.common.primitives.Bytes;
import org.jboss.netty.buffer.ChannelBuffer;
import org.onosproject.ospf.protocol.lsa.TlvHeader;
import org.onosproject.ospf.protocol.lsa.linksubtype.AdministrativeGroup;
import org.onosproject.ospf.protocol.lsa.linksubtype.LinkId;
import org.onosproject.ospf.protocol.lsa.linksubtype.LinkSubType;
import org.onosproject.ospf.protocol.lsa.linksubtype.LinkSubTypes;
import org.onosproject.ospf.protocol.lsa.linksubtype.LinkType;
import org.onosproject.ospf.protocol.lsa.linksubtype.LocalInterfaceIpAddress;
import org.onosproject.ospf.protocol.lsa.linksubtype.MaximumBandwidth;
import org.onosproject.ospf.protocol.lsa.linksubtype.MaximumReservableBandwidth;
import org.onosproject.ospf.protocol.lsa.linksubtype.RemoteInterfaceIpAddress;
import org.onosproject.ospf.protocol.lsa.linksubtype.TrafficEngineeringMetric;
import org.onosproject.ospf.protocol.lsa.linksubtype.UnknownLinkSubType;
import org.onosproject.ospf.protocol.lsa.linksubtype.UnreservedBandwidth;
import org.onosproject.ospf.protocol.lsa.types.TopLevelTlv;
import org.onosproject.ospf.protocol.util.OspfUtil;

import java.util.ArrayList;
import java.util.List;

/**
 * Representation of an OSPF Opaque link tlv.
 */
public class LinkTlv extends TlvHeader implements TopLevelTlv {
    private List<LinkSubType> subTlv = new ArrayList<>();

    /**
     * Creates an instance of link tlv.
     *
     * @param header tlv header
     */
    public LinkTlv(TlvHeader header) {
        this.setTlvType(header.tlvType());
        this.setTlvLength(header.tlvLength());
    }

    /**
     * Gets sub tlv lists.
     *
     * @return sub tlv lists
     */
    public List<LinkSubType> subTlvList() {
        return this.subTlv;
    }

    /**
     * Reads bytes from channel buffer .
     *
     * @param channelBuffer channel buffer instance
     * @throws Exception might throws exception while parsing packet
     */
    public void readFrom(ChannelBuffer channelBuffer) throws Exception {
        while (channelBuffer.readableBytes() > 0) {
            TlvHeader tlvHeader = new TlvHeader();
            tlvHeader.setTlvType(channelBuffer.readUnsignedShort());
            tlvHeader.setTlvLength(channelBuffer.readUnsignedShort());

            if (LinkSubTypes.LINK_TYPE.value() == tlvHeader.tlvType()) {
                LinkType linktype = new LinkType(tlvHeader);
                linktype.readFrom(channelBuffer.readBytes(tlvHeader.tlvLength()));
                subTlv.add(linktype);
                if (tlvHeader.tlvLength() < OspfUtil.FOUR_BYTES) {
                    int readerIndex = channelBuffer.readerIndex() + (OspfUtil.FOUR_BYTES - tlvHeader.tlvLength());
                    channelBuffer.readerIndex(readerIndex);
                }
            } else if (LinkSubTypes.LINK_ID.value() == tlvHeader.tlvType()) {
                LinkId linkId = new LinkId(tlvHeader);
                linkId.readFrom(channelBuffer.readBytes(tlvHeader.tlvLength()));
                subTlv.add(linkId);
            } else if (LinkSubTypes.LOCAL_INTERFACE_IP_ADDRESS.value() == tlvHeader.tlvType()) {
                LocalInterfaceIpAddress localInterfaceIpAddress = new LocalInterfaceIpAddress(tlvHeader);
                localInterfaceIpAddress.readFrom(channelBuffer.readBytes(tlvHeader.tlvLength()));
                subTlv.add(localInterfaceIpAddress);
            } else if (LinkSubTypes.REMOTE_INTERFACE_IP_ADDRESS.value() == tlvHeader.tlvType()) {
                RemoteInterfaceIpAddress remoteInterfaceIpAddress = new RemoteInterfaceIpAddress(tlvHeader);
                remoteInterfaceIpAddress.readFrom(channelBuffer.readBytes(tlvHeader.tlvLength()));
                subTlv.add(remoteInterfaceIpAddress);
            } else if (LinkSubTypes.TRAFFIC_ENGINEERING_METRIC.value() == tlvHeader.tlvType()) {
                TrafficEngineeringMetric trafficEngineeringMetric = new TrafficEngineeringMetric(tlvHeader);
                trafficEngineeringMetric.readFrom(channelBuffer.readBytes(tlvHeader.tlvLength()));
                subTlv.add(trafficEngineeringMetric);
            } else if (LinkSubTypes.MAXIMUM_BANDWIDTH.value() == tlvHeader.tlvType()) {
                MaximumBandwidth maximumBandwidth = new MaximumBandwidth(tlvHeader);
                maximumBandwidth.readFrom(channelBuffer.readBytes(tlvHeader.tlvLength()));
                subTlv.add(maximumBandwidth);
            } else if (LinkSubTypes.MAXIMUM_RESERVABLE_BANDWIDTH.value() == tlvHeader.tlvType()) {
                MaximumReservableBandwidth maximumReservableBandwidth = new MaximumReservableBandwidth(tlvHeader);
                maximumReservableBandwidth.readFrom(channelBuffer.readBytes(tlvHeader.tlvLength()));
                subTlv.add(maximumReservableBandwidth);
            } else if (LinkSubTypes.UNRESERVED_BANDWIDTH.value() == tlvHeader.tlvType()) {
                UnreservedBandwidth unreservedBandwidth = new UnreservedBandwidth(tlvHeader);
                unreservedBandwidth.readFrom(channelBuffer.readBytes(tlvHeader.tlvLength()));
                subTlv.add(unreservedBandwidth);
            } else if (LinkSubTypes.ADMINISTRATIVE_GROUP.value() == tlvHeader.tlvType()) {
                AdministrativeGroup administrativeGroup = new AdministrativeGroup(tlvHeader);
                administrativeGroup.readFrom(channelBuffer.readBytes(tlvHeader.tlvLength()));
                subTlv.add(administrativeGroup);
            } else {
                UnknownLinkSubType unknownLinkSubType = new UnknownLinkSubType(tlvHeader);
                unknownLinkSubType.readFrom(channelBuffer.readBytes(tlvHeader.tlvLength()));
                subTlv.add(unknownLinkSubType);
            }
        }
    }

    /**
     * Gets link tlv as byte array.
     *
     * @return link tlv as byte array
     * @throws Exception might throws exception while parsing buffer
     */
    public byte[] asBytes() throws Exception {
        byte[] lsaMessage = null;

        byte[] tlvHeader = getTlvHeaderAsByteArray();
        byte[] tlvBody = getTlvBodyAsByteArray();
        lsaMessage = Bytes.concat(tlvHeader, tlvBody);

        return lsaMessage;
    }

    /**
     * Gets tlv body as byte array.
     *
     * @return tlv body as byte array
     * @throws Exception might throws exception while parsing buffer
     */
    public byte[] getTlvBodyAsByteArray() throws Exception {

        List<Byte> bodyLst = new ArrayList<>();
        for (LinkSubType tlv : subTlv) {
            //Check the type of tlv and build bytes accordingly
            if (tlv instanceof LinkType) {
                LinkType linkType = (LinkType) tlv;
                bodyLst.addAll(Bytes.asList(linkType.asBytes()));
            } else if (tlv instanceof LinkId) {
                LinkId linkId = (LinkId) tlv;
                bodyLst.addAll(Bytes.asList(linkId.asBytes()));
            } else if (tlv instanceof LocalInterfaceIpAddress) {
                LocalInterfaceIpAddress localInterfaceIpAddress = (LocalInterfaceIpAddress) tlv;
                bodyLst.addAll(Bytes.asList(localInterfaceIpAddress.asBytes()));
            } else if (tlv instanceof RemoteInterfaceIpAddress) {
                RemoteInterfaceIpAddress remoteInterfaceIpAddress = (RemoteInterfaceIpAddress) tlv;
                bodyLst.addAll(Bytes.asList(remoteInterfaceIpAddress.asBytes()));
            } else if (tlv instanceof TrafficEngineeringMetric) {
                TrafficEngineeringMetric trafficEngineeringMetric = (TrafficEngineeringMetric) tlv;
                bodyLst.addAll(Bytes.asList(trafficEngineeringMetric.asBytes()));
            } else if (tlv instanceof MaximumBandwidth) {
                MaximumBandwidth maximumBandwidth = (MaximumBandwidth) tlv;
                bodyLst.addAll(Bytes.asList(maximumBandwidth.asBytes()));
            } else if (tlv instanceof MaximumReservableBandwidth) {
                MaximumReservableBandwidth maximumReservableBandwidth = (MaximumReservableBandwidth) tlv;
                bodyLst.addAll(Bytes.asList(maximumReservableBandwidth.asBytes()));
            } else if (tlv instanceof UnreservedBandwidth) {
                UnreservedBandwidth unreservedBandwidth = (UnreservedBandwidth) tlv;
                bodyLst.addAll(Bytes.asList(unreservedBandwidth.asBytes()));
            } else if (tlv instanceof AdministrativeGroup) {
                AdministrativeGroup administrativeGroup = (AdministrativeGroup) tlv;
                bodyLst.addAll(Bytes.asList(administrativeGroup.asBytes()));
            } else {
                UnknownLinkSubType unknownLinkSubType = (UnknownLinkSubType) tlv;
                bodyLst.addAll(Bytes.asList(unknownLinkSubType.asBytes()));
            }
        }
        return Bytes.toArray(bodyLst);
    }

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