/*
 * Copyright 2016-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.pcepio.types;

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.pcepio.exceptions.PcepParseException;
import org.onosproject.pcepio.protocol.PcepVersion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.MoreObjects;

/**
 * Provides LinkAttributesTlv.
 */
public class LinkAttributesTlv implements PcepValueType {

    /*
     * Reference :draft-dhodylee-pce-pcep-ls-01, section 9.2.8.2.
     *  0                   1                   2                   3
      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |           Type=[TBD27]        |             Length            |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                                                               |
     //              Link Attributes Sub-TLVs (variable)            //
     |                                                               |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     */

    private static final Logger log = LoggerFactory.getLogger(LinkAttributesTlv.class);

    public static final short TYPE = (short) 65286;
    short hLength;

    public static final int TLV_HEADER_LENGTH = 4;

    // LinkDescriptors Sub-TLVs (variable)
    private List<PcepValueType> llLinkAttributesSubTLVs;

    /**
     * Constructor to initialize Link Attributes Sub TLVs.
     *
     * @param llLinkAttributesSubTLVs linked list of PcepValueType
     */
    public LinkAttributesTlv(List<PcepValueType> llLinkAttributesSubTLVs) {
        this.llLinkAttributesSubTLVs = llLinkAttributesSubTLVs;
    }

    /**
     * Returns object of TE Link Attributes TLV.
     *
     * @param llLinkAttributesSubTLVs linked list of Link Attribute of Sub TLV
     * @return object of LinkAttributesTlv
     */
    public static LinkAttributesTlv of(final List<PcepValueType> llLinkAttributesSubTLVs) {
        return new LinkAttributesTlv(llLinkAttributesSubTLVs);
    }

    /**
     * Returns linked list of Link Attribute of Sub TLV.
     *
     * @return llLinkAttributesSubTLVs linked list of Link Attribute of Sub TLV
     */
    public List<PcepValueType> getllLinkAttributesSubTLVs() {
        return llLinkAttributesSubTLVs;
    }

    @Override
    public PcepVersion getVersion() {
        return PcepVersion.PCEP_1;
    }

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

    @Override
    public short getLength() {
        return hLength;
    }

    @Override
    public int hashCode() {
        return Objects.hash(llLinkAttributesSubTLVs.hashCode());
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        /*
         * Here we have a list of Tlv so to compare each sub tlv between the object
         * we have to take a list iterator so one by one we can get each sub tlv object
         * and can compare them.
         * it may be possible that the size of 2 lists is not equal so we have to first check
         * the size, if both are same then we should check for the subtlv objects otherwise
         * we should return false.
         */
        if (obj instanceof LinkAttributesTlv) {
            int countObjSubTlv = 0;
            int countOtherSubTlv = 0;
            boolean isCommonSubTlv = true;
            LinkAttributesTlv other = (LinkAttributesTlv) obj;
            Iterator<PcepValueType> objListIterator = ((LinkAttributesTlv) obj).llLinkAttributesSubTLVs.iterator();
            countObjSubTlv = ((LinkAttributesTlv) obj).llLinkAttributesSubTLVs.size();
            countOtherSubTlv = other.llLinkAttributesSubTLVs.size();
            if (countObjSubTlv != countOtherSubTlv) {
                return false;
            } else {
                while (objListIterator.hasNext() && isCommonSubTlv) {
                    PcepValueType subTlv = objListIterator.next();
                    isCommonSubTlv = Objects.equals(llLinkAttributesSubTLVs.contains(subTlv),
                            other.llLinkAttributesSubTLVs.contains(subTlv));
                }
                return isCommonSubTlv;
            }
        }
        return false;
    }

    @Override
    public int write(ChannelBuffer c) {
        int tlvStartIndex = c.writerIndex();
        c.writeShort(TYPE);
        int tlvLenIndex = c.writerIndex();
        hLength = 0;
        c.writeShort(hLength);

        ListIterator<PcepValueType> listIterator = llLinkAttributesSubTLVs.listIterator();

        while (listIterator.hasNext()) {
            PcepValueType tlv = listIterator.next();

            if (tlv == null) {
                log.debug("TLV is null from subTlv list");
                continue;
            }
            tlv.write(c);

            // need to take care of padding
            int pad = tlv.getLength() % 4;

            if (0 != pad) {
                pad = 4 - pad;
                for (int i = 0; i < pad; ++i) {
                    c.writeByte((byte) 0);
                }
            }
        }

        hLength = (short) (c.writerIndex() - tlvStartIndex);
        c.setShort(tlvLenIndex, (hLength - TLV_HEADER_LENGTH));

        return c.writerIndex() - tlvStartIndex;
    }

    /**
     * Reads channel buffer and returns object of TE Link Attributes TLV.
     *
     * @param c input channel buffer
     * @param hLength length
     * @return object of LinkAttributesTlv
     * @throws PcepParseException if mandatory fields are missing
     */
    public static PcepValueType read(ChannelBuffer c, short hLength) throws PcepParseException {

        // Node Descriptor Sub-TLVs (variable)
        List<PcepValueType> llLinkAttributesSubTLVs = new LinkedList<>();

        ChannelBuffer tempCb = c.readBytes(hLength);

        while (TLV_HEADER_LENGTH <= tempCb.readableBytes()) {

            PcepValueType tlv;
            short hType = tempCb.readShort();
            int iValue = 0;
            short length = tempCb.readShort();
            switch (hType) {

            case IPv4RouterIdOfLocalNodeSubTlv.TYPE:
                iValue = tempCb.readInt();
                tlv = new IPv4RouterIdOfLocalNodeSubTlv(iValue);
                break;
            case IPv6RouterIdofLocalNodeSubTlv.TYPE:
                byte[] ipv6LValue = new byte[IPv6RouterIdofLocalNodeSubTlv.VALUE_LENGTH];
                tempCb.readBytes(ipv6LValue, 0, IPv6RouterIdofLocalNodeSubTlv.VALUE_LENGTH);
                tlv = new IPv6RouterIdofLocalNodeSubTlv(ipv6LValue);
                break;
            case IPv4RouterIdOfRemoteNodeSubTlv.TYPE:
                iValue = tempCb.readInt();
                tlv = new IPv4RouterIdOfRemoteNodeSubTlv(iValue);
                break;
            case IPv6RouterIdofRemoteNodeSubTlv.TYPE:
                byte[] ipv6RValue = new byte[IPv6RouterIdofRemoteNodeSubTlv.VALUE_LENGTH];
                tempCb.readBytes(ipv6RValue, 0, IPv6RouterIdofRemoteNodeSubTlv.VALUE_LENGTH);
                tlv = new IPv6RouterIdofRemoteNodeSubTlv(ipv6RValue);
                break;
            case LinkLocalRemoteIdentifiersSubTlv.TYPE:
                tlv = LinkLocalRemoteIdentifiersSubTlv.read(tempCb);
                break;
            case AdministrativeGroupSubTlv.TYPE:
                iValue = tempCb.readInt();
                tlv = new AdministrativeGroupSubTlv(iValue);
                break;
            case MaximumLinkBandwidthSubTlv.TYPE:
                iValue = tempCb.readInt();
                tlv = new MaximumLinkBandwidthSubTlv(iValue);
                break;
            case MaximumReservableLinkBandwidthSubTlv.TYPE:
                iValue = tempCb.readInt();
                tlv = new MaximumReservableLinkBandwidthSubTlv(iValue);
                break;
            case UnreservedBandwidthSubTlv.TYPE:
                iValue = tempCb.readInt();
                tlv = new UnreservedBandwidthSubTlv(iValue);
                break;
            case TEDefaultMetricSubTlv.TYPE:
                iValue = tempCb.readInt();
                tlv = new TEDefaultMetricSubTlv(iValue);
                break;
            case LinkProtectionTypeSubTlv.TYPE:
                tlv = LinkProtectionTypeSubTlv.read(tempCb);
                break;
            case MplsProtocolMaskSubTlv.TYPE:
                byte cValue = tempCb.readByte();
                tlv = new MplsProtocolMaskSubTlv(cValue);
                break;
            case IgpMetricSubTlv.TYPE:
                tlv = IgpMetricSubTlv.read(tempCb, length);
                break;
            case SharedRiskLinkGroupSubTlv.TYPE:
                tlv = SharedRiskLinkGroupSubTlv.read(tempCb, length);
                break;
            case OpaqueLinkAttributeSubTlv.TYPE:
                tlv = OpaqueLinkAttributeSubTlv.read(tempCb, length);
                break;
            case LinkNameAttributeSubTlv.TYPE:
                tlv = LinkNameAttributeSubTlv.read(tempCb, length);
                break;
            default:
                throw new PcepParseException("Unsupported Sub TLV type :" + hType);
            }

            // Check for the padding
            int pad = length % 4;
            if (0 < pad) {
                pad = 4 - pad;
                if (pad <= tempCb.readableBytes()) {
                    tempCb.skipBytes(pad);
                }
            }
            llLinkAttributesSubTLVs.add(tlv);
        }

        if (0 < tempCb.readableBytes()) {

            throw new PcepParseException("Sub Tlv parsing error. Extra bytes received.");
        }

        return new LinkAttributesTlv(llLinkAttributesSubTLVs);
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(getClass())
                .add("Type", TYPE)
                .add("Length", hLength)
                .add("LinkAttributesSubTLVs", llLinkAttributesSubTLVs)
                .toString();
    }
}
