/*
 * 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;

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();

    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<PcInitiatedLspRequest>();

            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 (null == cb) {
                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();

    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 instanceof PcepSrpObject) {
                    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 instanceof PcepLspObject) {
                    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 instanceof PcepEndPointsObject) {
                        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 instanceof PcepEroObject) {
                        eroObj.write(cb);
                    } else {
                        throw new PcepParseException("ERO Object is mandatory for PcInitiate message.");
                    }

                    //PcepAttribute is optional
                    PcepAttribute pcepAttribute = listReq.getPcepAttribute();
                    if (pcepAttribute instanceof PcepAttribute) {
                        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();
    }
}
