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

/**
 * Provides PCEP SRP obejct.
 */
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 String toString() {
        return MoreObjects.toStringHelper(getClass()).add("RFlag", bRFlag).add("SRPID", srpId)
                .add("OptionalTlvList", llOptionalTlv).toString();
    }
}
