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

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 StatefulRsvpErrorSpecTlv.
 */
public class StatefulRsvpErrorSpecTlv implements PcepValueType {

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

    /*                  RSVP-ERROR-SPEC TLV format
     * Reference :PCEP Extensions for Stateful PCE draft-ietf-pce-stateful-pce-10
     *
     *

    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=21             |            Length (variable)  |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                                                               |
    +                RSVP ERROR_SPEC or USER_ERROR_SPEC Object      +
    |                                                               |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

        0             1              2             3
    +-------------+-------------+-------------+-------------+
    |       Length (bytes)      |  Class-Num  |   C-Type    |
    +-------------+-------------+-------------+-------------+
    |                                                       |
    //                  (Object contents)                   //
    |                                                       |
    +-------------+-------------+-------------+-------------+

    Ref :  ERROR_SPEC @ RFC2205

    IPv4 ERROR_SPEC object: Class = 6, C-Type = 1
    +-------------+-------------+-------------+-------------+
    |            IPv4 Error Node Address (4 bytes)          |
    +-------------+-------------+-------------+-------------+
    |    Flags    |  Error Code |        Error Value        |
    +-------------+-------------+-------------+-------------+


    IPv6 ERROR_SPEC object: Class = 6, C-Type = 2
    +-------------+-------------+-------------+-------------+
    |                                                       |
    +                                                       +
    |                                                       |
    +           IPv6 Error Node Address (16 bytes)          +
    |                                                       |
    +                                                       +
    |                                                       |
    +-------------+-------------+-------------+-------------+
    |    Flags    |  Error Code |        Error Value        |
    +-------------+-------------+-------------+-------------+


    Ref : USER_ERROR_SPEC @ RFC5284
    USER_ERROR_SPEC object: Class = 194, C-Type = 1
    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
    +---------------+---------------+---------------+---------------+
    |                       Enterprise Number                       |
    +---------------+---------------+---------------+---------------+
    |    Sub Org    |  Err Desc Len |        User Error Value       |
    +---------------+---------------+---------------+---------------+
    |                                                               |
    ~                       Error Description                       ~
    |                                                               |
    +---------------+---------------+---------------+---------------+
    |                                                               |
    ~                     User-Defined Subobjects                   ~
    |                                                               |
    +---------------+---------------+---------------+---------------+

     */

    public static final short TYPE = 21;
    public static final int OBJECT_HEADER_LENGTH = 4;
    private short hLength;

    private final PcepRsvpErrorSpec rsvpErrSpecObj;
    private final boolean isErrSpceObjSet;

    /**
     * Constructor to initialize errSpecObj.
     *
     * @param rsvpErrSpecObj Rsvp error spec object
     */
    public StatefulRsvpErrorSpecTlv(PcepRsvpErrorSpec rsvpErrSpecObj) {
        this.rsvpErrSpecObj = rsvpErrSpecObj;
        this.isErrSpceObjSet = true;
    }

    /**
     * Returns PcepRsvpErrorSpecObject.
     *
     * @return rsvpErrSpecObj
     */
    public PcepRsvpErrorSpec getPcepRsvpErrorSpec() {
        return this.rsvpErrSpecObj;
    }

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

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

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

    /**
     * Reads channel buffer and returns object of StatefulRsvpErrorSpecTlv.
     *
     * @param cb of type channel buffer
     * @return object of StatefulRsvpErrorSpecTlv
     * @throws PcepParseException while parsing this tlv from channel buffer
     */
    public static PcepValueType read(ChannelBuffer cb) throws PcepParseException {

        PcepRsvpErrorSpec rsvpErrSpecObj = null;
        PcepRsvpSpecObjHeader rsvpErrSpecObjHeader;

        cb.markReaderIndex();
        rsvpErrSpecObjHeader = PcepRsvpSpecObjHeader.read(cb);
        cb.resetReaderIndex();

        if (PcepRsvpIpv4ErrorSpec.CLASS_NUM == rsvpErrSpecObjHeader.getObjClassNum()
                && PcepRsvpIpv4ErrorSpec.CLASS_TYPE == rsvpErrSpecObjHeader.getObjClassType()) {
            rsvpErrSpecObj = PcepRsvpIpv4ErrorSpec.read(cb);
        } else if (PcepRsvpIpv6ErrorSpec.CLASS_NUM == rsvpErrSpecObjHeader.getObjClassNum()
                && PcepRsvpIpv6ErrorSpec.CLASS_TYPE == rsvpErrSpecObjHeader.getObjClassType()) {
            rsvpErrSpecObj = PcepRsvpIpv6ErrorSpec.read(cb);
        } else if (PcepRsvpUserErrorSpec.CLASS_NUM == rsvpErrSpecObjHeader.getObjClassNum()
                && PcepRsvpUserErrorSpec.CLASS_TYPE == rsvpErrSpecObjHeader.getObjClassType()) {
            rsvpErrSpecObj = PcepRsvpUserErrorSpec.read(cb);
        }
        return new StatefulRsvpErrorSpecTlv(rsvpErrSpecObj);
    }

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

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj instanceof StatefulRsvpErrorSpecTlv) {
            StatefulRsvpErrorSpecTlv other = (StatefulRsvpErrorSpecTlv) obj;
            return Objects.equals(this.rsvpErrSpecObj, other.rsvpErrSpecObj);
        }
        return false;
    }

    @Override
    public int write(ChannelBuffer c) {
        int iStartIndex = c.writerIndex();
        c.writeShort(TYPE);
        int tlvLenIndex = c.writerIndex();
        hLength = 0;
        c.writeShort(hLength);
        if (isErrSpceObjSet) {
            rsvpErrSpecObj.write(c);
        }
        hLength = (short) (c.writerIndex() - iStartIndex);
        c.setShort(tlvLenIndex, (hLength - OBJECT_HEADER_LENGTH));

        return c.writerIndex() - iStartIndex;
    }

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