/*
 * Copyright 2015-present 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<>();

    /**
     * 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<>();

        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<>();

        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();
    }
}
