/*
 * 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.PcepOpenObject;
import org.onosproject.pcepio.protocol.PcepType;
import org.onosproject.pcepio.protocol.PcepVersion;
import org.onosproject.pcepio.types.GmplsCapabilityTlv;
import org.onosproject.pcepio.types.PceccCapabilityTlv;
import org.onosproject.pcepio.types.PcepLabelDbVerTlv;
import org.onosproject.pcepio.types.PcepObjectHeader;
import org.onosproject.pcepio.types.PcepValueType;
import org.onosproject.pcepio.types.StatefulLspDbVerTlv;
import org.onosproject.pcepio.types.StatefulPceCapabilityTlv;
import org.onosproject.pcepio.types.TedCapabilityTlv;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.MoreObjects;

/**
 * Provides PCEP open object.
 */
public class PcepOpenObjectVer1 implements PcepOpenObject {

    /*
     message format.
      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)       |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    | Ver |   Flags |   Keepalive   |  DeadTimer    |      SID      |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                                                               |
    //                       Optional TLVs                         //
    |                                                               |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                     The OPEN Object format
     */
    protected static final Logger log = LoggerFactory.getLogger(PcepOpenObjectVer1.class);

    public static final PcepType MSG_TYPE = PcepType.OPEN;
    public static final byte OPEN_OBJECT_VERSION = 1;
    public static final byte OPEN_OBJ_TYPE = 1;
    public static final byte OPEN_OBJ_CLASS = 1;
    public static final byte DEFAULT_KEEPALIVE_TIME = 30;
    public static final byte DEFAULT_DEAD_TIME = 120;
    public static final short OPEN_OBJ_MINIMUM_LENGTH = 8;
    public static final int DEFAULT_GMPLS_CAPABILITY_TLV_IVALUE = 0X0;
    public static final int DEFAULT_STATEFUL_PCE_CAPABILITY_TLV_IVALUE = 0xf;
    public static final int DEFAULT_PCECC_CAPABILITY_TLV_IVALUE = 0x7;
    public static final int DEFAULT_PCEP_LABEL_DB_VER_TLV_IVALUE = 0X0;

    public static final PcepObjectHeader DEFAULT_OPEN_HEADER = new PcepObjectHeader(OPEN_OBJ_CLASS, OPEN_OBJ_TYPE,
            PcepObjectHeader.REQ_OBJ_OPTIONAL_PROCESS, PcepObjectHeader.RSP_OBJ_PROCESSED, OPEN_OBJ_MINIMUM_LENGTH);

    private PcepObjectHeader openObjHeader;
    private byte keepAliveTime;
    private byte deadTime;
    private byte sessionId;
    private LinkedList<PcepValueType> llOptionalTlv;

    /**
     * Default constructor.
     */
    public PcepOpenObjectVer1() {
        this.openObjHeader = null;
        this.keepAliveTime = 0;
        this.deadTime = 0;
        this.sessionId = 0;
        this.llOptionalTlv = null;
    }

    /**
     * Constructor to initialize all member variables.
     *
     * @param openObjHeader Open Object Header
     * @param keepAliveTime Keepalive timer value
     * @param deadTime      Dead timer value
     * @param sessionID     session id
     * @param llOptionalTlv Optional TLV
     */
    public PcepOpenObjectVer1(PcepObjectHeader openObjHeader, byte keepAliveTime, byte deadTime, byte sessionID,
            LinkedList<PcepValueType> llOptionalTlv) {
        this.openObjHeader = openObjHeader;
        this.keepAliveTime = keepAliveTime;
        this.deadTime = deadTime;
        this.sessionId = sessionID;
        this.llOptionalTlv = llOptionalTlv;
    }

    @Override
    public PcepObjectHeader getOpenObjHeader() {
        return this.openObjHeader;
    }

    @Override
    public void setOpenObjHeader(PcepObjectHeader obj) {
        this.openObjHeader = obj;
    }

    @Override
    public byte getKeepAliveTime() {
        return this.keepAliveTime;
    }

    @Override
    public void setKeepAliveTime(byte value) {
        this.keepAliveTime = value;
    }

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

    @Override
    public byte getDeadTime() {
        return this.deadTime;
    }

    @Override
    public void setDeadTime(byte value) {
        this.deadTime = value;
    }

    @Override
    public byte getSessionId() {
        return this.sessionId;
    }

    @Override
    public void setSessionId(byte value) {
        this.sessionId = value;
    }

    @Override
    public LinkedList<PcepValueType> getOptionalTlv() {
        return this.llOptionalTlv;
    }

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

    /**
     * Reads from channel buffer and returns object of PcepOpenObject.
     *
     * @param cb of type channel buffer
     * @return object of PcepOpenObject
     * @throws PcepParseException if mandatory fields are missing
     */
    public static PcepOpenObject read(ChannelBuffer cb) throws PcepParseException {

        PcepObjectHeader openObjHeader;
        byte version;
        byte keepAliveTime;
        byte deadTime;
        byte sessionID;
        LinkedList<PcepValueType> llOptionalTlv;

        openObjHeader = PcepObjectHeader.read(cb);
        version = cb.readByte();
        version = (byte) (version >> PcepMessageVer1.SHIFT_FLAG);
        if (version != OPEN_OBJECT_VERSION) {
            throw new PcepParseException("Wrong version: Expected=PcepVersion.PCEP_1(1), got=" + version);
        }
        /* Keepalive */
        keepAliveTime = cb.readByte();

        /* DeadTimer */
        deadTime = cb.readByte();

        /* SID */
        sessionID = cb.readByte();

        // Optional TLV
        llOptionalTlv = parseOptionalTlv(cb);

        return new PcepOpenObjectVer1(openObjHeader, keepAliveTime, deadTime, sessionID, llOptionalTlv);
    }

    /**
     * Returns linkedlist of optional tlvs.
     *
     * @param cb of type channel buffer
     * @return llOptionalTlv Optional TLV
     * @throws PcepParseException if mandatory fields are missing
     */
    protected static LinkedList<PcepValueType> parseOptionalTlv(ChannelBuffer cb) throws PcepParseException {

        LinkedList<PcepValueType> llOptionalTlv;

        llOptionalTlv = new LinkedList<>();

        while (4 <= cb.readableBytes()) {
            PcepValueType tlv;
            short hType = cb.readShort();
            short hLength = cb.readShort();

            switch (hType) {
            case GmplsCapabilityTlv.TYPE:
                log.debug("GmplsCapabilityTlv");
                if (GmplsCapabilityTlv.LENGTH != hLength) {
                    throw new PcepParseException("Invalid length received for Gmpls_Capability_Tlv.");
                }
                int iValue = cb.readInt();
                tlv = new GmplsCapabilityTlv(iValue);
                break;
            case StatefulPceCapabilityTlv.TYPE:
                log.debug("StatefulPceCapabilityTlv");
                if (StatefulPceCapabilityTlv.LENGTH != hLength) {
                    throw new PcepParseException("Invalid length received for StatefulPceCapabilityTlv.");
                }
                tlv = StatefulPceCapabilityTlv.read(cb);
                break;
            case PceccCapabilityTlv.TYPE:
                log.debug("PceccCapabilityTlv");
                if (PceccCapabilityTlv.LENGTH != hLength) {
                    throw new PcepParseException("Invalid length for PceccCapabilityTlv.");
                }
                iValue = cb.readInt();
                tlv = new PceccCapabilityTlv(iValue);
                break;
            case StatefulLspDbVerTlv.TYPE:
                log.debug("StatefulLspDbVerTlv");
                if (StatefulLspDbVerTlv.LENGTH != hLength) {
                    throw new PcepParseException("Invalid length received for StatefulLspDbVerTlv.");
                }
                long lValue = cb.readLong();
                tlv = new StatefulLspDbVerTlv(lValue);
                break;
            case TedCapabilityTlv.TYPE:
                log.debug("TedCapabilityTlv");
                if (TedCapabilityTlv.LENGTH != hLength) {
                    throw new PcepParseException("Invalid length received for TedCapabilityTlv.");
                }
                iValue = cb.readInt();
                tlv = new TedCapabilityTlv(iValue);
                break;
            case PcepLabelDbVerTlv.TYPE:
                log.debug("PcepLabelDbVerTlv");
                if (PcepLabelDbVerTlv.LENGTH != hLength) {
                    throw new PcepParseException("Invalid length received for PcepLabelDbVerTlv.");
                }
                lValue = cb.readLong();
                tlv = new PcepLabelDbVerTlv(lValue);
                break;
            default:
                log.debug("Unsupported TLV: " + hType);
                cb.skipBytes(hLength);
                continue;
            }

            llOptionalTlv.add(tlv);
        }

        if (0 < cb.readableBytes()) {
            throw new PcepParseException("Optional Tlv parsing error. Extra bytes received.");
        }

        return llOptionalTlv;
    }

    @Override
    public int write(ChannelBuffer cb) throws PcepParseException {

        int objStartIndex = cb.writerIndex();

        //write common header
        int objLenIndex = openObjHeader.write(cb);

        if (objLenIndex <= 0) {
            throw new PcepParseException("Unable to write Open object header.");
        }

        cb.writeByte((byte) (OPEN_OBJECT_VERSION << PcepMessageVer1.SHIFT_FLAG));
        cb.writeByte(this.keepAliveTime);
        cb.writeByte(this.deadTime);
        cb.writeByte(this.sessionId);

        //Pack optional TLV
        packOptionalTlv(cb);

        //now write OPEN Object Length
        int length = cb.writerIndex() - objStartIndex;
        cb.setShort(objLenIndex, (short) length);
        //will be helpful during print().
        this.openObjHeader.setObjLen((short) length);

        return length;
    }

    /**
     * Returns writer index.
     *
     * @param cb of type channel buffer.
     * @return writer index
     */
    protected int packOptionalTlv(ChannelBuffer cb) {
        int startIndex = cb.writerIndex();

        LinkedList<PcepValueType> llOptionalTlv = this.llOptionalTlv;
        ListIterator<PcepValueType> listIterator = llOptionalTlv.listIterator();
        while (listIterator.hasNext()) {
            PcepValueType tlv = listIterator.next();
            if (tlv == null) {
                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 cb.writerIndex() - startIndex;
    }

    /**
     * Builder class for PCPE open object.
     */
    public static class Builder implements PcepOpenObject.Builder {
        // Pcep open message fields
        private boolean bIsHeaderSet = false;
        private PcepObjectHeader openObjHeader;
        private boolean bIsKeepAliveTimeSet = false;
        private byte keepAliveTime;
        private boolean bIsDeadTimeSet = false;
        private byte deadTime;
        private boolean bIsSessionIDSet = false;
        private byte sessionID;
        private boolean bIsOptionalTlvSet = false;
        private LinkedList<PcepValueType> llOptionalTlv = new LinkedList<>();

        private boolean bIsPFlagSet = false;
        private boolean bPFlag;

        private boolean bIsIFlagSet = false;
        private boolean bIFlag;

        @Override
        public PcepOpenObject build() throws PcepParseException {
            PcepObjectHeader openObjHeader = this.bIsHeaderSet ? this.openObjHeader : DEFAULT_OPEN_HEADER;
            byte keepAliveTime = this.bIsKeepAliveTimeSet ? this.keepAliveTime : DEFAULT_KEEPALIVE_TIME;
            byte deadTime = this.bIsDeadTimeSet ? this.deadTime : DEFAULT_DEAD_TIME;

            if (!this.bIsSessionIDSet) {
                throw new PcepParseException("SessionID is not set (mandatory)");
            }
            if (!this.bIsOptionalTlvSet) {
                //Add tlv to list
                //Add GmplsCapabilityTlv
                PcepValueType tlv;
                int iValue = DEFAULT_GMPLS_CAPABILITY_TLV_IVALUE;
                tlv = new GmplsCapabilityTlv(iValue);
                this.llOptionalTlv.add(tlv);

                //Add StatefulPceCapabilityTlv
                iValue = DEFAULT_STATEFUL_PCE_CAPABILITY_TLV_IVALUE;
                tlv = new StatefulPceCapabilityTlv(iValue);
                this.llOptionalTlv.add(tlv);

            }

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

            if (bIsIFlagSet) {
                openObjHeader.setIFlag(bIFlag);
            }

            return new PcepOpenObjectVer1(openObjHeader, keepAliveTime, deadTime, this.sessionID, this.llOptionalTlv);
        }

        @Override
        public PcepObjectHeader getOpenObjHeader() {
            return this.openObjHeader;
        }

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

        @Override
        public byte getKeepAliveTime() {
            return this.keepAliveTime;
        }

        @Override
        public Builder setKeepAliveTime(byte value) {
            this.keepAliveTime = value;
            this.bIsKeepAliveTimeSet = true;
            return this;
        }

        @Override
        public byte getDeadTime() {
            return this.deadTime;
        }

        @Override
        public Builder setDeadTime(byte value) {
            this.deadTime = value;
            this.bIsDeadTimeSet = true;
            return this;
        }

        @Override
        public byte getSessionId() {
            return this.sessionID;
        }

        @Override
        public Builder setSessionId(byte value) {
            this.sessionID = value;
            this.bIsSessionIDSet = true;
            return this;
        }

        @Override
        public Builder setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) {
            this.llOptionalTlv = llOptionalTlv;
            this.bIsOptionalTlvSet = true;
            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("ObjectHeader", openObjHeader)
                .add("Keepalive", keepAliveTime)
                .add("DeadTimer", deadTime)
                .add("SessionId", sessionId)
                .add("OptionalTlv", llOptionalTlv)
                .toString();
    }
}
