/*
 * Copyright 2015-present 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.PcepReportMsg;
import org.onosproject.pcepio.protocol.PcepSrpObject;
import org.onosproject.pcepio.protocol.PcepStateReport;
import org.onosproject.pcepio.protocol.PcepType;
import org.onosproject.pcepio.protocol.PcepVersion;
import org.onosproject.pcepio.types.PcepObjectHeader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.MoreObjects;

/**
 * Provides PCEP report message.
 */
class PcepReportMsgVer1 implements PcepReportMsg {

    // Pcep version: 1

    /*
     * The format of the PCRpt message is as follows:
     *   <PCRpt Message>        ::= <Common Header>
     *                              <state-report-list>
     *Where:
     *   <state-report-list>    ::= <state-report>[<state-report-list>]
     *   <state-report>         ::= [<SRP>]
     *                              <LSP>
     *                              <path>
     * Where:
     *   <path>                 ::= <ERO><attribute-list>[<RRO>]
     *   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>]
     */
    protected static final Logger log = LoggerFactory.getLogger(PcepReportMsgVer1.class);

    public static final byte PACKET_VERSION = 1;
    //PACKET_MINIMUM_LENGTH = CommonHeaderLen(4)+LspObjMinLen(8)+EroObjMinLen(12)
    public static final int PACKET_MINIMUM_LENGTH = 24;
    public static final PcepType MSG_TYPE = PcepType.REPORT;
    public static final byte REPORT_OBJ_TYPE = 1;
    //Optional TLV
    private LinkedList<PcepStateReport> llStateReportList;

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

    /**
     * Reader class for reading PCEP report message from channel buffer.
     */
    static class Reader implements PcepMessageReader<PcepReportMsg> {

        LinkedList<PcepStateReport> llStateReportList;

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

            if (cb.readableBytes() < PACKET_MINIMUM_LENGTH) {
                throw new PcepParseException("Received packet size " + cb.readableBytes()
                        + " is less than the expected size: " + PACKET_MINIMUM_LENGTH);
            }
            llStateReportList = new LinkedList<>();
            byte version = cb.readByte();
            version = (byte) (version >> PcepMessageVer1.SHIFT_FLAG);

            if (version != PACKET_VERSION) {
                throw new PcepParseException(" Invalid version: " + version);
            }

            byte type = cb.readByte();

            if (type != MSG_TYPE.getType()) {
                throw new PcepParseException("Unexpected type: " + type);
            }

            short length = cb.readShort();

            if (length < PACKET_MINIMUM_LENGTH) {
                throw new PcepParseException("Wrong length. Expected to be >= " + PACKET_MINIMUM_LENGTH + ", was: "
                        + length);
            }
            // parse state report list
            parseStateReportList(cb);
            return new PcepReportMsgVer1(llStateReportList);
        }

        // Parse State Report list
        public void parseStateReportList(ChannelBuffer cb) throws PcepParseException {

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

             */

            while (0 < cb.readableBytes()) {

                PcepStateReport pcestateReq = new PcepStateReportVer1();

                /*
                 * SRP is optional
                 * Check whether SRP Object is available, if yes store it.
                 * First read common object header and check the Object Class whether it is SRP or LSP
                 * If it is LSP then store only LSP. So, SRP is optional. then read path and store.
                 * If it is SRP then store SRP and then read LSP, path and store them.
                 */

                //mark the reader index to reset
                cb.markReaderIndex();
                PcepObjectHeader tempObjHeader = PcepObjectHeader.read(cb);

                byte yObjectClass = tempObjHeader.getObjClass();
                byte yObjectType = tempObjHeader.getObjType();

                //reset reader index
                cb.resetReaderIndex();
                //If SRP present then store it.
                if ((PcepSrpObjectVer1.SRP_OBJ_CLASS == yObjectClass)
                        && (PcepSrpObjectVer1.SRP_OBJ_TYPE == yObjectType)) {
                    PcepSrpObject srpObj;
                    srpObj = PcepSrpObjectVer1.read(cb);
                    pcestateReq.setSrpObject(srpObj);
                }

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

                //store path
                PcepStateReport.PcepMsgPath msgPath = new PcepStateReportVer1().new PcepMsgPath().read(cb);
                pcestateReq.setMsgPath(msgPath);

                llStateReportList.add(pcestateReq);
            }
        }
    }

    /**
     * Constructor to initialize State Report List.
     *
     * @param llStateReportList list of type Pcep state report
     */
    PcepReportMsgVer1(LinkedList<PcepStateReport> llStateReportList) {
        this.llStateReportList = llStateReportList;
    }

    /**
     * Builder class for PCEP Report message.
     */
    static class Builder implements PcepReportMsg.Builder {
        // Pcep report message fields
        LinkedList<PcepStateReport> llStateReportList;

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

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

        @Override
        public PcepReportMsg build() {
            return new PcepReportMsgVer1(this.llStateReportList);
        }

        @Override
        public LinkedList<PcepStateReport> getStateReportList() {
            return this.llStateReportList;
        }

        @Override
        public Builder setStateReportList(LinkedList<PcepStateReport> ll) {
            this.llStateReportList = 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 report message to channel buffer.
     */
    static class Writer implements PcepMessageWriter<PcepReportMsgVer1> {

        @Override
        public void write(ChannelBuffer cb, PcepReportMsgVer1 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<PcepStateReport> listIterator = message.llStateReportList.listIterator();

            while (listIterator.hasNext()) {

                PcepStateReport stateRpt = listIterator.next();
                PcepSrpObject srpObj = stateRpt.getSrpObject();

                //SRP object is optional
                if (srpObj != null) {
                    srpObj.write(cb);
                }

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

                //path is mandatory
                PcepStateReport.PcepMsgPath msgPath = stateRpt.getMsgPath();
                if (msgPath == null) {
                    throw new PcepParseException("Message path is mandatory object for PcRpt message.");
                } else {
                    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<PcepStateReport> getStateReportList() {
        return this.llStateReportList;
    }

    @Override
    public void setStateReportList(LinkedList<PcepStateReport> ll) {
        this.llStateReportList = ll;
    }

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