/*
 * 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.protocol.ver1;

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.PcepRroObject;
import org.onosproject.pcepio.types.IPv4SubObject;
import org.onosproject.pcepio.types.IPv6SubObject;
import org.onosproject.pcepio.types.LabelSubObject;
import org.onosproject.pcepio.types.PcepObjectHeader;
import org.onosproject.pcepio.types.PcepValueType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.MoreObjects;

/**
 * Provides PCEP RRO object.
 */
public class PcepRroObjectVer1 implements PcepRroObject {

    /*
     * rfc3209
          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
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         | Object-Class  |   OT  |Res|P|I|   Object Length (bytes)       |
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         |                                                               |
         //                        (Subobjects)                          //
         |                                                               |
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

            Each subobject has its own Length
            field.  The length contains the total length of the subobject in
            bytes, including the Type and Length fields.  The length MUST always
            be a multiple of 4, and at least 4.

            An empty RRO with no subobjects is considered illegal.
            Three kinds of subobjects are currently defined.

           Subobject 1: IPv4 address

            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     |     Length    | IPv4 address (4 bytes)        |
           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
           | IPv4 address (continued)      | Prefix Length |      Flags    |
           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

           Subobject 2: IPv6 address

            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     |     Length    | IPv6 address (16 bytes)       |
           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
           | IPv6 address (continued)                                      |
           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
           | IPv6 address (continued)                                      |
           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
           | IPv6 address (continued)                                      |
           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
           | IPv6 address (continued)      | Prefix Length |      Flags    |
           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

           Subobject 3, Label

            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      |     Length    |    Flags      |   C-Type      |
           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
           |       Contents of Label Object                                |
           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

     */
    protected static final Logger log = LoggerFactory.getLogger(PcepRroObjectVer1.class);

    public static final byte RRO_OBJ_TYPE = 1;
    public static final byte RRO_OBJ_CLASS = 8;
    public static final byte RRO_OBJECT_VERSION = 1;
    public static final short RRO_OBJ_MINIMUM_LENGTH = 12;
    public static final int OBJECT_HEADER_LENGTH = 4;
    public static final int YTYPE_SHIFT_VALUE = 0x7F;

    static final PcepObjectHeader DEFAULT_RRO_OBJECT_HEADER = new PcepObjectHeader(RRO_OBJ_CLASS, RRO_OBJ_TYPE,
            PcepObjectHeader.REQ_OBJ_OPTIONAL_PROCESS, PcepObjectHeader.RSP_OBJ_PROCESSED, RRO_OBJ_MINIMUM_LENGTH);

    private short rroObjType = 0;
    private byte length;
    private byte prefixLength;
    private byte resvd;
    PcepObjectHeader rroObjHeader;
    private LinkedList<PcepValueType> llSubObjects = new LinkedList<PcepValueType>();

    /**
     * Reset variables.
     */
    public PcepRroObjectVer1() {
        this.rroObjHeader = null;
        this.rroObjType = 0;
        this.length = 0;
    }

    /**
     * constructor to initialize parameters for RRO object.
     *
     * @param rroObjHeader RRO object header
     * @param llSubObjects list of sub objects
     */
    public PcepRroObjectVer1(PcepObjectHeader rroObjHeader, LinkedList<PcepValueType> llSubObjects) {
        this.rroObjHeader = rroObjHeader;
        this.llSubObjects = llSubObjects;
    }

    /**
     * Returns PCEP RRO Object Header.
     *
     * @return rroObjHeader RRO Object header
     */
    public PcepObjectHeader getRroObjHeader() {
        return this.rroObjHeader;
    }

    /**
     * Sets PCEP RRO Object Header.
     *
     * @param obj Object header
     */
    public void setRroObjHeader(PcepObjectHeader obj) {
        this.rroObjHeader = obj;
    }

    @Override
    public LinkedList<PcepValueType> getSubObjects() {
        return this.llSubObjects;
    }

    @Override
    public void setSubObjects(LinkedList<PcepValueType> llSubObjects) {
        this.llSubObjects = llSubObjects;
    }

    /**
     * Reads the channel buffer and returns object of PcepRroObject.
     *
     * @param cb of type channel buffer
     * @return object of PcepRroObject
     * @throws PcepParseException when fails to read from channel buffer
     */
    public static PcepRroObject read(ChannelBuffer cb) throws PcepParseException {

        PcepObjectHeader rroObjHeader;
        LinkedList<PcepValueType> llSubObjects;
        rroObjHeader = PcepObjectHeader.read(cb);

        //take only RroObject buffer.
        ChannelBuffer tempCb = cb.readBytes(rroObjHeader.getObjLen() - OBJECT_HEADER_LENGTH);
        llSubObjects = parseSubObjects(tempCb);

        return new PcepRroObjectVer1(rroObjHeader, llSubObjects);
    }

    /**
     * Returns list of sub objects.
     *
     * @param cb of type channel buffer
     * @return list of sub objects
     * @throws PcepParseException when fails to parse list of sub objects
     */
    protected static LinkedList<PcepValueType> parseSubObjects(ChannelBuffer cb) throws PcepParseException {

        LinkedList<PcepValueType> llSubObjects = new LinkedList<PcepValueType>();

        while (0 < cb.readableBytes()) {

            //check the Type of the Sub objects
            byte yType = cb.readByte();
            yType = (byte) (yType & (YTYPE_SHIFT_VALUE));
            byte hLength = cb.readByte();

            PcepValueType subObj;

            switch (yType) {

            case IPv4SubObject.TYPE:
                subObj = IPv4SubObject.read(cb);
                break;
            case IPv6SubObject.TYPE:
                byte[] ipv6Value = new byte[IPv6SubObject.VALUE_LENGTH];
                cb.readBytes(ipv6Value, 0, IPv6SubObject.VALUE_LENGTH);
                subObj = new IPv6SubObject(ipv6Value);
                break;
            case LabelSubObject.TYPE:
                subObj = LabelSubObject.read(cb);
                break;
            default:
                throw new PcepParseException(" Unexpected sub object. Type: " + (int) yType);
            }
            // Check for the padding
            int pad = hLength % 4;
            if (0 < pad) {
                pad = 4 - pad;
                if (pad <= cb.readableBytes()) {
                    cb.skipBytes(pad);
                }
            }
            llSubObjects.add(subObj);
        }

        return llSubObjects;
    }

    @Override
    public int write(ChannelBuffer cb) throws PcepParseException {
        //write Object header
        int objStartIndex = cb.writerIndex();

        int objLenIndex = rroObjHeader.write(cb);

        if (objLenIndex <= 0) {
            throw new PcepParseException(" object Length Index" + objLenIndex);
        }

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

        while (listIterator.hasNext()) {
            listIterator.next().write(cb);
        }

        //Update object length now
        int length = cb.writerIndex() - objStartIndex;
        cb.setShort(objLenIndex, (short) length);
        //will be helpful during print().
        rroObjHeader.setObjLen((short) length);

        //As per RFC the length of object should be multiples of 4
        int pad = length % 4;

        if (0 != pad) {
            pad = 4 - pad;
            for (int i = 0; i < pad; i++) {
                cb.writeByte((byte) 0);
            }
            length = length + pad;
        }
        objLenIndex = cb.writerIndex();
        return objLenIndex;
    }

    /**
     * Builder class for PCEP RRO object.
     */
    public static class Builder implements PcepRroObject.Builder {
        private boolean bIsHeaderSet = false;

        private PcepObjectHeader rroObjHeader;
        LinkedList<PcepValueType> llSubObjects = new LinkedList<PcepValueType>();

        private boolean bIsPFlagSet = false;
        private boolean bPFlag;

        private boolean bIsIFlagSet = false;
        private boolean bIFlag;

        @Override
        public PcepRroObject build() {

            PcepObjectHeader rroObjHeader = this.bIsHeaderSet ? this.rroObjHeader : DEFAULT_RRO_OBJECT_HEADER;

            if (bIsPFlagSet) {
                rroObjHeader.setPFlag(bPFlag);
            }

            if (bIsIFlagSet) {
                rroObjHeader.setIFlag(bIFlag);
            }
            return new PcepRroObjectVer1(rroObjHeader, this.llSubObjects);
        }

        @Override
        public PcepObjectHeader getRroObjHeader() {
            return this.rroObjHeader;
        }

        @Override
        public Builder setRroObjHeader(PcepObjectHeader obj) {
            this.rroObjHeader = obj;
            this.bIsHeaderSet = true;
            return this;
        }

        @Override
        public LinkedList<PcepValueType> getSubObjects() {
            return this.llSubObjects;
        }

        @Override
        public Builder setSubObjects(LinkedList<PcepValueType> llSubObjects) {
            this.llSubObjects = llSubObjects;
            return this;
        }

        @Override
        public Builder setPFlag(boolean value) {
            this.bPFlag = value;
            this.bIsPFlagSet = true;
            return this;
        }

        @Override
        public Builder setIFlag(boolean value) {
            this.bIFlag = value;
            this.bIsIFlagSet = true;
            return this;
        }
    }

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