/*
 * 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.PcepLspObject;
import org.onosproject.pcepio.protocol.PcepMessageReader;
import org.onosproject.pcepio.protocol.PcepMessageWriter;
import org.onosproject.pcepio.protocol.PcepMsgPath;
import org.onosproject.pcepio.protocol.PcepSrpObject;
import org.onosproject.pcepio.protocol.PcepType;
import org.onosproject.pcepio.protocol.PcepUpdateMsg;
import org.onosproject.pcepio.protocol.PcepUpdateRequest;
import org.onosproject.pcepio.protocol.PcepVersion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.MoreObjects;

/**
 * Provides PCEP update message.
 */

class PcepUpdateMsgVer1 implements PcepUpdateMsg {

    // Pcep version: 1

    /*    The format of the PCUpd message is as follows:
     *      <PCUpd Message>             ::= <Common Header>
     *                                       <update-request-list>
     *      Where:
     *        <update-request-list>     ::= <update-request>[<update-request-list>]
     *        <update-request>          ::= <SRP>
     *                                      <LSP>
     *                                      <path>
     *      Where:
     *        <path>                     ::= <ERO><attribute-list>
     *       Where:
     *        <attribute-list> is defined in [RFC5440] and extended by PCEP extensions.
     *       where:
     *        <attribute-list>            ::=[<LSPA>]
     *                                      [<BANDWIDTH>]
     *                                      [<metric-list>]
     *                                      [<IRO>]
     *        <metric-list>               ::=<METRIC>[<metric-list>]
     *
     *            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
     *          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     *          | Ver |  Flags  |  Message-Type |       Message-Length          |
     *          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     *          |                                                               |
     *          //                  UPDATE REQUEST LIST                        //
     *          |                                                               |
     *          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     *
     *          Reference:Internet-Draft-PCEP Extensions-for-Stateful-PCE-10
     */

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

    public static final byte PACKET_VERSION = 1;
    // UpdateMsgMinLength = SrpObjMinLentgh(12)+LspObjMinLength(8)+EroObjMinLength(12)+ CommonHeaderLength(4)
    public static final short PACKET_MINIMUM_LENGTH = 36;
    public static final PcepType MSG_TYPE = PcepType.UPDATE;
    //Update Request List
    private LinkedList<PcepUpdateRequest> llUpdateRequestList;

    public static final PcepUpdateMsgVer1.Reader READER = new Reader();

    /**
     * Reader reads UpdateMessage from the channel.
     */
    static class Reader implements PcepMessageReader<PcepUpdateMsg> {

        LinkedList<PcepUpdateRequest> llUpdateRequestList;

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

            if (cb.readableBytes() < PACKET_MINIMUM_LENGTH) {
                throw new PcepParseException("Readable bytes is less than update message minimum length");
            }

            llUpdateRequestList = new LinkedList<PcepUpdateRequest>();

            // fixed value property version == 1
            byte version = cb.readByte();
            version = (byte) (version >> PcepMessageVer1.SHIFT_FLAG);
            if (version != PACKET_VERSION) {
                throw new PcepParseException("Wrong version. Expected=PcepVersion.PCEP_1(1), got=" + version);
            }
            // fixed value property type == 11
            byte type = cb.readByte();
            if (type != MSG_TYPE.getType()) {
                throw new PcepParseException("Wrong type. Expected=PcepType.UPDATE(11), got=" + type);
            }
            short length = cb.readShort();
            if (length < PACKET_MINIMUM_LENGTH) {
                throw new PcepParseException("Wrong length. Expected to be >= " + PACKET_MINIMUM_LENGTH + ", was: "
                        + length);
            }

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

            // parse Update Request list
            if (!parseUpdateRequestList(cb)) {
                throw new PcepParseException("parsing Update Request List Failed.");
            }

            return new PcepUpdateMsgVer1(llUpdateRequestList);
        }

        /**
         * Parse update request list.
         *
         * @param cb of type channel buffer
         * @return true after parsing Update Request List
         * @throws PcepParseException while parsing update request list from channel buffer
         */
        public boolean parseUpdateRequestList(ChannelBuffer cb) throws PcepParseException {

            /*                     <update-request-list>
             * Where:
             *   <update-request-list>     ::= <update-request>[<update-request-list>]
             *   <update-request>          ::= <SRP>
             *                                 <LSP>
             *                                 <path>
             * Where:
             *   <path>                     ::= <ERO><attribute-list>
             * Where:
             * <attribute-list> is defined in [RFC5440] and extended by PCEP extensions.
             */

            while (0 < cb.readableBytes()) {

                PcepUpdateRequest pceUpdateReq = new PcepUpdateRequestVer1();

                //Read SRP Object and Store it.
                PcepSrpObject srpObj;
                srpObj = PcepSrpObjectVer1.read(cb);
                pceUpdateReq.setSrpObject(srpObj);

                //Read LSP object and Store it.
                PcepLspObject lspObj;
                lspObj = PcepLspObjectVer1.read(cb);
                pceUpdateReq.setLspObject(lspObj);

                // Read Msg Path and store it.
                PcepMsgPath msgPath = new PcepMsgPathVer1().read(cb);
                pceUpdateReq.setMsgPath(msgPath);

                llUpdateRequestList.add(pceUpdateReq);
            }
            return true;
        }
    }

    /**
     * Constructor to initialize llUpdateRequestList.
     *
     * @param llUpdateRequestList list of PcepUpdateRequest.
     */
    PcepUpdateMsgVer1(LinkedList<PcepUpdateRequest> llUpdateRequestList) {
        this.llUpdateRequestList = llUpdateRequestList;
    }

    /**
     * Builder class for PCPE update message.
     */
    static class Builder implements PcepUpdateMsg.Builder {

        // PCEP report message fields
        LinkedList<PcepUpdateRequest> llUpdateRequestList;

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

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

        @Override
        public PcepUpdateMsg build() {
            return new PcepUpdateMsgVer1(this.llUpdateRequestList);
        }

        @Override
        public LinkedList<PcepUpdateRequest> getUpdateRequestList() {
            return this.llUpdateRequestList;
        }

        @Override
        public Builder setUpdateRequestList(LinkedList<PcepUpdateRequest> llUpdateRequestList) {
            this.llUpdateRequestList = llUpdateRequestList;
            return this;
        }

    }

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

    static final Writer WRITER = new Writer();

    /**
     * Writer writes UpdateMessage to the channel buffer.
     */
    static class Writer implements PcepMessageWriter<PcepUpdateMsgVer1> {

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

            int startIndex = cb.writerIndex();
            // first 3 bits set to version
            cb.writeByte((byte) (PACKET_VERSION << PcepMessageVer1.SHIFT_FLAG));
            // message type
            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((short) 0);
            ListIterator<PcepUpdateRequest> listIterator = message.llUpdateRequestList.listIterator();

            while (listIterator.hasNext()) {

                PcepUpdateRequest updateReq = listIterator.next();

                //SRP object is mandatory
                PcepSrpObject srpObj = updateReq.getSrpObject();
                srpObj.write(cb);

                //LSP object is mandatory
                PcepLspObject lspObj = updateReq.getLspObject();
                lspObj.write(cb);

                //PATH object is mandatory
                PcepMsgPath msgPath = updateReq.getMsgPath();
                msgPath.write(cb);
            }

            // update 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<PcepUpdateRequest> getUpdateRequestList() {
        return this.llUpdateRequestList;
    }

    @Override
    public void setUpdateRequestList(LinkedList<PcepUpdateRequest> llUpdateRequestList) {
        this.llUpdateRequestList = llUpdateRequestList;
    }

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