/*
 * 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.PcInitiatedLspRequest;
import org.onosproject.pcepio.protocol.PcepAttribute;
import org.onosproject.pcepio.protocol.PcepEndPointsObject;
import org.onosproject.pcepio.protocol.PcepEroObject;
import org.onosproject.pcepio.protocol.PcepInitiateMsg;
import org.onosproject.pcepio.protocol.PcepLspObject;
import org.onosproject.pcepio.protocol.PcepMessageReader;
import org.onosproject.pcepio.protocol.PcepMessageWriter;
import org.onosproject.pcepio.protocol.PcepSrpObject;
import org.onosproject.pcepio.protocol.PcepType;
import org.onosproject.pcepio.protocol.PcepVersion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.MoreObjects;

/**
 * Provides PCEP initiate message.
 */
class PcepInitiateMsgVer1 implements PcepInitiateMsg {

    protected static final Logger log = LoggerFactory.getLogger(PcepInitiateMsgVer1.class);

    // Ref : PCE initiated tunnel setup draft-ietf-pce-pce-initiated-lsp-03, section 5.1
    /*      <PCInitiate Message>             ::= <Common Header>
     *                                           <PCE-initiated-lsp-list>
     *    Where:
     *      <PCE-initiated-lsp-list>          ::= <PCE-initiated-lsp-request>[<PCE-initiated-lsp-list>]
     *      <PCE-initiated-lsp-request>       ::= (<PCE-initiated-lsp-instantiation>|<PCE-initiated-lsp-deletion>)
     *      <PCE-initiated-lsp-instantiation> ::= <SRP>
     *                                            <LSP>
     *                                            <END-POINTS>
     *                                            <ERO>
     *                                            [<attribute-list>]
     *     <PCE-initiated-lsp-deletion>      ::= <SRP>
     *                                           <LSP>
     */

    static final byte PACKET_VERSION = 1;
    /* considering LspDelete Request PcInitiate msg will contain
     * common header
     * srp object
     * lsp object
     * so min length for this can be
     * PACKET_MINIMUM_LENGTH = CommonHeaderLen(4)+SrpObjectMinLen(12)+LspObjectMinLen(8)
     */
    public static final short PACKET_MINIMUM_LENGTH = 24;
    public static final short MINIMUM_COMMON_HEADER_LENGTH = 4;
    public static final PcepType MSG_TYPE = PcepType.INITIATE;
    private LinkedList<PcInitiatedLspRequest> llPcInitiatedLspRequestList;
    public static final PcepInitiateMsgVer1.Reader READER = new Reader();

    /**
     * Reader class for reading of Pcep initiate message from channel buffer.
     */
    static class Reader implements PcepMessageReader<PcepInitiateMsg> {

        LinkedList<PcInitiatedLspRequest> llPcInitiatedLspRequestList;

        @Override
        public PcepInitiateMsg readFrom(ChannelBuffer cb) throws PcepParseException {

            if (cb.readableBytes() < PACKET_MINIMUM_LENGTH) {
                return null;
            }

            llPcInitiatedLspRequestList = new LinkedList<>();

            byte version = cb.readByte();
            version = (byte) (version >> PcepMessageVer1.SHIFT_FLAG);
            if (version != PACKET_VERSION) {
                throw new PcepParseException("Wrong version. Expected=PcepVersion.PCEP_1(1), received=" + version);
            }
            byte type = cb.readByte();
            if (type != MSG_TYPE.getType()) {
                throw new PcepParseException("Wrong type. Expected=PcepType.INITIATE(12), recived=" + type);
            }
            short length = cb.readShort();

            if (length < PACKET_MINIMUM_LENGTH) {
                throw new PcepParseException("Wrong length. Initiate message length expected to be >= "
                        + PACKET_MINIMUM_LENGTH + ", but received=" + length);
            }

            log.debug("reading PcInitiate message of length " + length);

            // parse Start initiate/deletion list
            if (!parsePcInitiatedLspRequestList(cb)) {
                throw new PcepParseException("Parsing PCE-initiated-lsp-Request-list failed");
            }

            return new PcepInitiateMsgVer1(llPcInitiatedLspRequestList);
        }

        /**
         * To parse PcInitiatedLspRequestList from PcInitiate Message.
         *
         * @param cb of type channel buffer
         * @return true if parsing PcInitiatedLspRequestList is success, false otherwise
         * @throws PcepParseException while parsing from channel buffer
         */
        public boolean parsePcInitiatedLspRequestList(ChannelBuffer cb) throws PcepParseException {

            boolean isDelLspRequest = false;

            if (cb == null) {
                throw new PcepParseException("Channel buffer is empty");
            }

            while (0 < cb.readableBytes()) {
                PcInitiatedLspRequest pceInitLspReq = new PcInitiatedLspRequestVer1();

                //store SRP object
                PcepSrpObject srpObj;
                srpObj = PcepSrpObjectVer1.read(cb);
                pceInitLspReq.setSrpObject(srpObj);
                isDelLspRequest = srpObj.getRFlag();

                //store LSP object
                PcepLspObject lspObj;
                lspObj = PcepLspObjectVer1.read(cb);
                pceInitLspReq.setLspObject(lspObj);

                /* if R bit will be set then pcInitiate msg will contain only LSp and SRP objects
                 * so if R bit is not set then we should read for Ero and EndPoint objects also.
                 */
                if (!isDelLspRequest) {

                    //store EndPoint object
                    PcepEndPointsObject endPointObj;
                    endPointObj = PcepEndPointsObjectVer1.read(cb);
                    pceInitLspReq.setEndPointsObject(endPointObj);

                    //store ERO object
                    PcepEroObject eroObj;
                    eroObj = PcepEroObjectVer1.read(cb);
                    pceInitLspReq.setEroObject(eroObj);

                    if (cb.readableBytes() > MINIMUM_COMMON_HEADER_LENGTH) {
                        pceInitLspReq.setPcepAttribute(PcepAttributeVer1.read(cb));
                    }
                }
                llPcInitiatedLspRequestList.add(pceInitLspReq);
            }
            return true;
        }
    }

    /**
     * Constructor to initialize PcInitiatedLspRequest.
     *
     * @param llPcInitiatedLspRequestList list of PcInitiatedLspRequest
     */
    PcepInitiateMsgVer1(LinkedList<PcInitiatedLspRequest> llPcInitiatedLspRequestList) {

        if (llPcInitiatedLspRequestList == null) {
            throw new NullPointerException("PcInitiatedLspRequestList cannot be null.");
        }
        this.llPcInitiatedLspRequestList = llPcInitiatedLspRequestList;
    }

    /**
     * Builder class for PCEP initiate message.
     */
    static class Builder implements PcepInitiateMsg.Builder {

        // Pcep initiate message fields
        LinkedList<PcInitiatedLspRequest> llPcInitiatedLspRequestList;

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

        @Override
        public PcepType getType() {
            return PcepType.INITIATE;
        }

        @Override
        public PcepInitiateMsg build() {
            return new PcepInitiateMsgVer1(this.llPcInitiatedLspRequestList);
        }

        @Override
        public LinkedList<PcInitiatedLspRequest> getPcInitiatedLspRequestList() {
            return this.llPcInitiatedLspRequestList;
        }

        @Override
        public Builder setPcInitiatedLspRequestList(LinkedList<PcInitiatedLspRequest> ll) {
            this.llPcInitiatedLspRequestList = ll;
            return this;
        }
    }

    @Override
    public void writeTo(ChannelBuffer cb) throws PcepParseException {
        WRITER.write(cb, this);
    }

    static final Writer WRITER = new Writer();

    /**
     * Writer class for writing pcep initiate message to channel buffer.
     */
    static class Writer implements PcepMessageWriter<PcepInitiateMsgVer1> {

        @Override
        public void write(ChannelBuffer cb, PcepInitiateMsgVer1 message) throws PcepParseException {

            boolean isDelLspRequest = false;
            int startIndex = cb.writerIndex();
            // first 3 bits set to version
            cb.writeByte((byte) (PACKET_VERSION << PcepMessageVer1.SHIFT_FLAG));
            // message type 0xC
            cb.writeByte(MSG_TYPE.getType());
            // length is length of variable message, will be updated at the end
            // Store the position of message
            // length in buffer
            int msgLenIndex = cb.writerIndex();
            cb.writeShort(0);

            ListIterator<PcInitiatedLspRequest> listIterator = message.llPcInitiatedLspRequestList.listIterator();

            while (listIterator.hasNext()) {

                PcInitiatedLspRequest listReq = listIterator.next();

                //Srp Object is mandatory
                PcepSrpObject srpObj = listReq.getSrpObject();
                if (srpObj != null) {
                    isDelLspRequest = srpObj.getRFlag();
                    srpObj.write(cb);
                } else {
                    throw new PcepParseException("SRP Object is mandatory for PcInitiate message.");
                }

                //LSP Object is mandatory
                PcepLspObject lspObj = listReq.getLspObject();
                if (lspObj != null) {
                    lspObj.write(cb);
                } else {
                    throw new PcepParseException("LSP Object is mandatory for PcInitiate message.");
                }

                /* if R bit will be set then pcInitiate msg will contain only LSp and SRP objects
                 * so if R bit is not set then we should read for Ero and EndPoint objects also.
                 */

                if (!isDelLspRequest) {

                    //EndPoints object is mandatory
                    PcepEndPointsObject endPointObj = listReq.getEndPointsObject();
                    if (endPointObj != null) {
                        endPointObj.write(cb);
                    } else {
                        throw new PcepParseException("End points Object is mandatory for PcInitiate message.");
                    }

                    //Ero object is mandatory
                    PcepEroObject eroObj = listReq.getEroObject();
                    if (eroObj != null) {
                        eroObj.write(cb);
                    } else {
                        throw new PcepParseException("ERO Object is mandatory for PcInitiate message.");
                    }

                    //PcepAttribute is optional
                    PcepAttribute pcepAttribute = listReq.getPcepAttribute();
                    if (pcepAttribute != null) {
                        pcepAttribute.write(cb);
                    }
                }
            }

            // PCInitiate message length field
            int length = cb.writerIndex() - startIndex;
            cb.setShort(msgLenIndex, (short) length);
        }
    }

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

    @Override
    public PcepType getType() {
        return MSG_TYPE;
    }

    @Override
    public LinkedList<PcInitiatedLspRequest> getPcInitiatedLspRequestList() {
        return this.llPcInitiatedLspRequestList;
    }

    @Override
    public void setPcInitiatedLspRequestList(LinkedList<PcInitiatedLspRequest> ll) {
        this.llPcInitiatedLspRequestList = ll;
    }

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