/*
 * 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.PcepSrpObject;
import org.onosproject.pcepio.types.PcepObjectHeader;
import org.onosproject.pcepio.types.PcepValueType;
import org.onosproject.pcepio.types.SymbolicPathNameTlv;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.MoreObjects;

public class PcepSrpObjectVer1 implements PcepSrpObject {

    /*
     * ref : draft-ietf-pce-stateful-pce-10, section : 7.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
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    | Object-Class  |   OT  |Res|P|I|   Object Length (bytes)       |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                          Flags                              |R|
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                        SRP-ID-number                          |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                                                               |
    //                      Optional TLVs                          //
    |                                                               |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

     */
    protected static final Logger log = LoggerFactory.getLogger(PcepSrpObjectVer1.class);

    public static final byte SRP_OBJ_TYPE = 1;
    public static final byte SRP_OBJ_CLASS = 33;
    public static final byte SRP_OBJECT_VERSION = 1;
    public static final short SRP_OBJ_MINIMUM_LENGTH = 12;
    public static final int MINIMUM_COMMON_HEADER_LENGTH = 4;
    public static final boolean DEFAULT_RFLAG = false;

    static final PcepObjectHeader DEFAULT_SRP_OBJECT_HEADER = new PcepObjectHeader(SRP_OBJ_CLASS, SRP_OBJ_TYPE,
            PcepObjectHeader.REQ_OBJ_OPTIONAL_PROCESS, PcepObjectHeader.RSP_OBJ_PROCESSED, SRP_OBJ_MINIMUM_LENGTH);

    private PcepObjectHeader srpObjHeader;
    private static int flags;
    private boolean bRFlag;
    private int srpId;

    //Optional TLV
    private LinkedList<PcepValueType> llOptionalTlv;
    public static final byte BBIT_SET = 1;
    public static final byte BBIT_RESET = 0;

    /**
     * Constructor to initialize member variables.
     *
     * @param srpObjHeader srp object header
     * @param bRFlag R flag
     * @param srpID srp Id
     * @param llOptionalTlv list of optional tlv
     */
    public PcepSrpObjectVer1(PcepObjectHeader srpObjHeader, boolean bRFlag, int srpID,
            LinkedList<PcepValueType> llOptionalTlv) {

        this.srpObjHeader = srpObjHeader;
        this.bRFlag = bRFlag;
        this.srpId = srpID;
        this.llOptionalTlv = llOptionalTlv;
    }

    /**
     * sets the SRP object header.
     *
     * @param obj srp object header
     */
    public void setSrpObjHeader(PcepObjectHeader obj) {
        this.srpObjHeader = obj;
    }

    @Override
    public void setSrpID(int srpID) {
        this.srpId = srpID;
    }

    @Override
    public void setRFlag(boolean bRFlag) {
        this.bRFlag = bRFlag;
    }

    /**
     * Returns SRP object header.
     *
     * @return srpObjHeader
     */
    public PcepObjectHeader getSrpObjHeader() {
        return this.srpObjHeader;
    }

    @Override
    public int getSrpID() {
        return this.srpId;
    }

    @Override
    public boolean getRFlag() {
        return this.bRFlag;
    }

    @Override
    public void setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) {
        this.llOptionalTlv = llOptionalTlv;

    }

    @Override
    public LinkedList<PcepValueType> getOptionalTlv() {
        return this.llOptionalTlv;
    }

    /**
     * Reads from channel buffer and returns instance of PCEP SRP object.
     *
     * @param cb of channel buffer.
     * @return PCEP SRP object
     * @throws PcepParseException when srp object is not received in channel buffer
     */
    public static PcepSrpObject read(ChannelBuffer cb) throws PcepParseException {

        log.debug("SrpObject::read");
        PcepObjectHeader srpObjHeader;
        boolean bRFlag;

        int srpID;
        int flags;
        LinkedList<PcepValueType> llOptionalTlv = new LinkedList<PcepValueType>();

        srpObjHeader = PcepObjectHeader.read(cb);

        if (SRP_OBJ_CLASS != srpObjHeader.getObjClass()) {
            throw new PcepParseException("SRP object expected. But received " + srpObjHeader.getObjClass());
        }

        //take only SrpObject buffer.
        ChannelBuffer tempCb = cb.readBytes(srpObjHeader.getObjLen() - MINIMUM_COMMON_HEADER_LENGTH);
        flags = tempCb.readInt();
        bRFlag = (0 < flags) ? true : false;
        srpID = tempCb.readInt();

        llOptionalTlv = parseOptionalTlv(tempCb);

        return new PcepSrpObjectVer1(srpObjHeader, bRFlag, srpID, llOptionalTlv);
    }

    @Override
    public int write(ChannelBuffer cb) throws PcepParseException {

        int objStartIndex = cb.writerIndex();

        //write common header
        int objLenIndex = srpObjHeader.write(cb);

        //write Flags
        byte bFlag;

        bFlag = (bRFlag) ? BBIT_SET : BBIT_RESET;

        cb.writeInt(bFlag);

        //write SrpId
        cb.writeInt(srpId);

        // Add optional TLV
        if (!packOptionalTlv(cb)) {
            throw new PcepParseException("Failed to write srp tlv to channel buffer.");
        }

        //now write SRP Object Length
        cb.setShort(objLenIndex, (short) (cb.writerIndex() - objStartIndex));

        return cb.writerIndex();
    }

    /**
     * Parse Optional TLvs from the channel buffer.
     *
     * @param cb of type channel buffer
     * @return list of optional tlvs
     * @throws PcepParseException when unsupported tlv is received in srp object
     */
    public static LinkedList<PcepValueType> parseOptionalTlv(ChannelBuffer cb) throws PcepParseException {

        LinkedList<PcepValueType> llOutOptionalTlv = new LinkedList<PcepValueType>();

        while (MINIMUM_COMMON_HEADER_LENGTH <= cb.readableBytes()) {

            PcepValueType tlv;
            short hType = cb.readShort();
            short hLength = cb.readShort();

            switch (hType) {

            case SymbolicPathNameTlv.TYPE:
                tlv = SymbolicPathNameTlv.read(cb, hLength);
                cb.skipBytes(hLength);
                break;

            default:
                throw new PcepParseException("Unsupported TLV received in SRP Object.");
            }

            // Check for the padding
            int pad = hLength % 4;
            if (0 < pad) {
                pad = 4 - pad;
                if (pad <= cb.readableBytes()) {
                    cb.skipBytes(pad);
                }
            }
            llOutOptionalTlv.add(tlv);
        }

        return llOutOptionalTlv;
    }

    /**
     * Writes optional tlvs to channel buffer.
     *
     * @param cb of type channel buffer
     * @return true if writing optional tlv to channel buffer is success.
     */
    protected boolean packOptionalTlv(ChannelBuffer cb) {

        ListIterator<PcepValueType> listIterator = llOptionalTlv.listIterator();

        while (listIterator.hasNext()) {
            PcepValueType tlv = listIterator.next();

            if (null == tlv) {
                log.debug("tlv is null from OptionalTlv list");
                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);
                }
            }
        }

        return true;
    }

    /**
     * builder class for PCEP srp Object.
     */
    public static class Builder implements PcepSrpObject.Builder {
        private boolean bIsHeaderSet = false;
        private boolean bIsSrpIdset = false;
        private boolean bIsRFlagSet = false;

        private PcepObjectHeader srpObjHeader;
        private int srpId;
        private boolean bRFlag;
        LinkedList<PcepValueType> llOptionalTlv = new LinkedList<PcepValueType>();

        private boolean bIsPFlagSet = false;
        private boolean bPFlag;

        private boolean bIsIFlagSet = false;
        private boolean bIFlag;

        @Override
        public PcepSrpObject build() throws PcepParseException {
            PcepObjectHeader srpObjHeader = this.bIsHeaderSet ? this.srpObjHeader : DEFAULT_SRP_OBJECT_HEADER;

            boolean bRFlag = this.bIsRFlagSet ? this.bRFlag : DEFAULT_RFLAG;

            if (!this.bIsSrpIdset) {
                throw new PcepParseException("SrpID not set while building SRP Object.");
            }

            if (bIsPFlagSet) {
                srpObjHeader.setPFlag(bPFlag);
            }

            if (bIsIFlagSet) {
                srpObjHeader.setIFlag(bIFlag);
            }

            return new PcepSrpObjectVer1(srpObjHeader, bRFlag, this.srpId, this.llOptionalTlv);
        }

        @Override
        public PcepObjectHeader getSrpObjHeader() {
            return this.srpObjHeader;
        }

        @Override
        public Builder setSrpObjHeader(PcepObjectHeader obj) {
            this.srpObjHeader = obj;
            this.bIsHeaderSet = true;
            return this;
        }

        @Override
        public int getSrpID() {
            return this.srpId;
        }

        @Override
        public Builder setSrpID(int srpID) {
            this.srpId = srpID;
            this.bIsSrpIdset = true;
            return this;
        }

        @Override
        public boolean getRFlag() {
            return this.bRFlag;
        }

        @Override
        public Builder setRFlag(boolean bRFlag) {
            this.bRFlag = bRFlag;
            this.bIsRFlagSet = true;
            return this;
        }

        @Override
        public Builder setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) {
            this.llOptionalTlv = llOptionalTlv;
            return this;
        }

        @Override
        public LinkedList<PcepValueType> getOptionalTlv() {
            return this.llOptionalTlv;
        }

        @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 void print() {

        log.debug("SRP OBJECT");
        long lTemp = (bRFlag) ? 1 : 0;
        log.debug("r Flag: " + lTemp);
        log.debug("SrpID: " + srpId);

        log.debug("OPTIONAL TLV");
        ListIterator<PcepValueType> listIterator = llOptionalTlv.listIterator();
        while (listIterator.hasNext()) {
            listIterator.next().print();
        }
    }
    @Override
    public String toString() {
        return MoreObjects.toStringHelper(getClass())
                .add("R flag", bRFlag)
                .add("SRP ID", srpId)
                .add("Optional tlv list", llOptionalTlv)
                .toString();
    }
}
