/*
 * 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.LinkedList;
import java.util.ListIterator;

import org.jboss.netty.buffer.ChannelBuffer;
import org.onosproject.pcepio.exceptions.PcepParseException;
import org.onosproject.pcepio.protocol.PcepVersion;

import com.google.common.base.MoreObjects;

/**
 * Provides Pcep Rsvp User Error Spec.
 */
public class PcepRsvpUserErrorSpec implements PcepRsvpErrorSpec {

    /*
        RSVP error spec object header.
        0             1              2             3
    +-------------+-------------+-------------+-------------+
    |       Length (bytes)      |  Class-Num  |   C-Type    |
    +-------------+-------------+-------------+-------------+
    |                                                       |
    //                  (Object contents)                   //
    |                                                       |
    +-------------+-------------+-------------+-------------+

    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 byte CLASS_NUM = (byte) 0xc2;
    public static final byte CLASS_TYPE = 0x01;

    private PcepRsvpSpecObjHeader objHeader;
    private int enterpriseNum;
    private byte subOrg;
    private byte errDescLen;
    private short userErrorValue;
    private byte[] errDesc;
    private LinkedList<PcepValueType> llRsvpUserSpecSubObj;

    /**
     * Default constructor.
     *
     * @param objHeader pcep rsvp spec object header
     * @param enterpriseNum enterprise number
     * @param subOrg organization identifier value
     * @param errDescLen error description length
     * @param userErrorValue user error value
     * @param errDesc error description
     * @param llRsvpUserSpecSubObj list of subobjects
     */
    public PcepRsvpUserErrorSpec(PcepRsvpSpecObjHeader objHeader, int enterpriseNum, byte subOrg, byte errDescLen,
            short userErrorValue, byte[] errDesc, LinkedList<PcepValueType> llRsvpUserSpecSubObj) {
        this.objHeader = objHeader;
        this.enterpriseNum = enterpriseNum;
        this.subOrg = subOrg;
        this.errDescLen = errDescLen;
        this.userErrorValue = userErrorValue;
        this.errDesc = errDesc;
        this.llRsvpUserSpecSubObj = llRsvpUserSpecSubObj;
    }

    @Override
    public int write(ChannelBuffer cb) {
        int objLenIndex = objHeader.write(cb);
        cb.writeInt(enterpriseNum);
        cb.writeByte(subOrg);
        cb.writeByte(errDescLen);
        cb.writeShort(userErrorValue);
        cb.writeBytes(errDesc);

        if (null != llRsvpUserSpecSubObj) {

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

            while (listIterator.hasNext()) {
                PcepValueType tlv = listIterator.next();
                if (null == tlv) {
                    continue;
                }
                tlv.write(cb);
                // need to take care of padding
                int pad = tlv.getLength() % 4;
                if (0 != pad) {
                    pad = 4 - pad;
                    for (int i = 0; i < pad; ++i) {
                        cb.writeByte((byte) 0);
                    }
                }
            }
        }
        short objLen = (short) (cb.writerIndex() - objLenIndex);
        cb.setShort(objLenIndex, objLen);
        return objLen;
    }

    /**
     * Reads the channel buffer and returns object of PcepRsvpErrorSpec.
     *
     * @param cb of type channel buffer
     * @return object of PcepRsvpErrorSpec
     * @throws PcepParseException when expected object is not received
     */
    public static PcepRsvpErrorSpec read(ChannelBuffer cb) throws PcepParseException {
        PcepRsvpSpecObjHeader objHeader;
        int enterpriseNum;
        byte subOrg;
        byte errDescLen;
        short userErrorValue;
        byte[] errDesc;
        LinkedList<PcepValueType> llRsvpUserSpecSubObj = null;

        objHeader = PcepRsvpSpecObjHeader.read(cb);

        if (CLASS_NUM != objHeader.getObjClassNum() || CLASS_TYPE != objHeader.getObjClassType()) {
            throw new PcepParseException("Expected PcepRsvpUserErrorSpec object.");
        }
        enterpriseNum = cb.readInt();
        subOrg = cb.readByte();
        errDescLen = cb.readByte();
        userErrorValue = cb.readShort();
        errDesc = new byte[errDescLen];
        cb.readBytes(errDesc, 0, errDescLen);

        llRsvpUserSpecSubObj = parseErrSpecSubObj(cb);

        return new PcepRsvpUserErrorSpec(objHeader, enterpriseNum, subOrg, errDescLen, userErrorValue, errDesc,
                llRsvpUserSpecSubObj);
    }

    private static LinkedList<PcepValueType> parseErrSpecSubObj(ChannelBuffer cb) throws PcepParseException {
        LinkedList<PcepValueType> llRsvpUserSpecSubObj = new LinkedList<PcepValueType>();
        while (0 < cb.readableBytes()) {
            PcepValueType tlv = null;
            short hType = cb.readShort();
            int iValue = 0;
            //short hLength = cb.readShort();
            switch (hType) {
            case AutonomousSystemTlv.TYPE:
                iValue = cb.readInt();
                tlv = new AutonomousSystemTlv(iValue);
                break;
            default:
                throw new PcepParseException("Unsupported Sub TLV type :" + hType);
            }
            llRsvpUserSpecSubObj.add(tlv);
        }
        return llRsvpUserSpecSubObj;
    }

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

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

    @Override
    public short getLength() {
        return objHeader.getObjLen();
    }

    @Override
    public byte getClassNum() {
        return CLASS_NUM;
    }

    @Override
    public byte getClassType() {
        return CLASS_TYPE;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(getClass())
                .add("enterpriseNumber:", enterpriseNum)
                .add("subOrganization:", subOrg)
                .add("errDescLength:", errDescLen)
                .add("userErrorValue:", userErrorValue)
                .add("errDesc:", errDesc)
                .add("RsvpUserSpecSubObject:", llRsvpUserSpecSubObj)
                .toString();
    }
}
