/*
 * 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 org.jboss.netty.buffer.ChannelBuffer;
import org.onosproject.pcepio.exceptions.PcepParseException;
import org.onosproject.pcepio.protocol.PcepAttribute;
import org.onosproject.pcepio.protocol.PcepBandwidthObject;
import org.onosproject.pcepio.protocol.PcepEroObject;
import org.onosproject.pcepio.protocol.PcepLspObject;
import org.onosproject.pcepio.protocol.PcepRroObject;
import org.onosproject.pcepio.protocol.PcepSrpObject;
import org.onosproject.pcepio.protocol.PcepStateReport;
import org.onosproject.pcepio.types.PcepObjectHeader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.MoreObjects;
import com.google.common.base.MoreObjects.ToStringHelper;

/**
 * Provide the State Report for the Pcep Report Message.
 * Reference :PCE extensions for stateful draft-ietf-pce-stateful-pce-10.
 */
public class PcepStateReportVer1 implements PcepStateReport {
    /*
     * <state-report>     ::= [<SRP>]
                               <LSP>
                               <path>
       Where:
               <path>     ::= <ERO><attribute-list>[<RRO>]
     */

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

    public static final int OBJECT_HEADER_LENGTH = 4;

    /**
     * Provides PCEP Message path for report message.
     */
    public class PcepMsgPath implements PcepStateReport.PcepMsgPath {

        /*
         * <path>                  ::= <ERO><attribute-list>[<RRO>]
         */

        //PcepEroObject
        private PcepEroObject eroObj;
        private boolean isEroObjectSet;
        //PcepAttribute List
        private PcepAttribute attrList;
        private boolean isAttributeListSet;
        //PcepRroObject
        private PcepRroObject rroObj;
        private boolean isRroObjectSet;
        private PcepBandwidthObject bandwidth;
        private boolean isBandwidthObjectSet;

        /**
         * Constructor to reset the parameters.
         */
        public PcepMsgPath() {
            eroObj = null;
            attrList = null;
            rroObj = null;
            this.isEroObjectSet = false;
            this.isAttributeListSet = false;
            this.isRroObjectSet = false;
            this.isBandwidthObjectSet = false;
        }

        /**
         * Constructor to initialize the parameters from PCEP Message path.
         *
         * @param eroObj PCEP ERO Object
         * @param attrList PCEP Attribute
         * @param rroObj PCEP Rro Object
         * @param bandwidth PCEP bandwidth object
         */
        public PcepMsgPath(PcepEroObject eroObj, PcepAttribute attrList, PcepRroObject rroObj,
                           PcepBandwidthObject bandwidth) {

            this.eroObj = eroObj;
            this.attrList = attrList;
            this.rroObj = rroObj;
            this.bandwidth = bandwidth;
            if (null == rroObj) {
                this.isRroObjectSet = false;
            } else {
                this.isRroObjectSet = true;
            }
            if (null == eroObj) {
                this.isEroObjectSet = false;
            } else {
                this.isEroObjectSet = true;
            }
            if (null == attrList) {
                this.isAttributeListSet = false;
            } else {
                this.isAttributeListSet = true;
            }
            if (null == bandwidth) {
                this.isBandwidthObjectSet = false;
            } else {
                this.isBandwidthObjectSet = true;
            }
        }

        /**
         * Returns PcepEroObject.
         *
         * @return eroObj PCEP ERO Object
         */
        @Override
        public PcepEroObject getEroObject() {
            return this.eroObj;
        }

        /**
         * Returns PCEP Attribute.
         *
         * @return attrList Attribute list
         */
        @Override
        public PcepAttribute getPcepAttribute() {
            return this.attrList;
        }

        /**
         * Returns PcepRroObject.
         *
         * @return rroObj PCEP RRO Object
         */
        @Override
        public PcepRroObject getRroObject() {
            return this.rroObj;
        }

        @Override
        public PcepBandwidthObject getBandwidthObject() {
            return this.bandwidth;
        }

        @Override
        public void setEroObject(PcepEroObject eroObj) {
            this.eroObj = eroObj;
        }

        @Override
        public void setPcepAttribute(PcepAttribute attrList) {
            this.attrList = attrList;
        }

        @Override
        public void setRroObject(PcepRroObject rroObj) {
            this.rroObj = rroObj;
        }

        @Override
        public void setBandwidthObject(PcepBandwidthObject bandwidth) {
            this.bandwidth = bandwidth;
        }

        /**
         * Reads all the Objects for PCEP Message Path.
         *
         * @param bb of type channel buffer
         * @return PCEP Message path
         * @throws PcepParseException when fails to read pcep message path
         */
        @Override
        public PcepMsgPath read(ChannelBuffer bb) throws PcepParseException {

            PcepEroObject eroObj;
            PcepAttribute attrList;
            PcepRroObject rroObj = null;
            PcepBandwidthObject bandwidth = null;

            eroObj = PcepEroObjectVer1.read(bb);
            attrList = PcepAttributeVer1.read(bb);

            boolean bBreakWhile = false;
            while (0 < bb.readableBytes()) {

                if (bb.readableBytes() < OBJECT_HEADER_LENGTH) {
                    break;
                }
                bb.markReaderIndex();
                PcepObjectHeader tempObjHeader = PcepObjectHeader.read(bb);
                bb.resetReaderIndex();
                byte yObjClass = tempObjHeader.getObjClass();

                switch (yObjClass) {
                case PcepRroObjectVer1.RRO_OBJ_CLASS:
                    rroObj = PcepRroObjectVer1.read(bb);
                    break;
                case PcepInterLayerObjectVer1.INTER_LAYER_OBJ_CLASS:
                    bb.skipBytes(tempObjHeader.getObjLen());
                    break;
                case PcepBandwidthObjectVer1.BANDWIDTH_OBJ_CLASS:
                    bandwidth = PcepBandwidthObjectVer1.read(bb);
                    break;
                default:
                    //Otherthan above objects handle those objects in caller.
                    bBreakWhile = true;
                    break;
                }
                if (bBreakWhile) {
                    break;
                }
            }
            return new PcepMsgPath(eroObj, attrList, rroObj, bandwidth);
        }

        /**
         * Writes all the objects for PCEP message path.
         *
         * @param bb of type channel buffer.
         * @return object length index
         * @throws PcepParseException when fails to write to channel buffer
         */
        @Override
        public int write(ChannelBuffer bb) throws PcepParseException {
            int iLenStartIndex = bb.writerIndex();

            //write Object header
            if (this.isEroObjectSet) {
                this.eroObj.write(bb);
            } else {
                throw new PcepParseException("Ero object is not set in path");
            }

            if (this.isAttributeListSet) {
                this.attrList.write(bb);
            }

            // RRO is optional check and read
            if (this.isRroObjectSet) {
                this.rroObj.write(bb);
                // bandwidth should come along with RRO.
                if (this.isBandwidthObjectSet) {
                    this.bandwidth.write(bb);
                }
            }
            return bb.writerIndex() - iLenStartIndex;
        }

        @Override
        public String toString() {
            ToStringHelper toStrHelper = MoreObjects.toStringHelper(getClass());

            if (attrList instanceof PcepAttribute) {
                toStrHelper.add("AttributeList", attrList);
            }
            if (rroObj instanceof PcepRroObjectVer1) {
                toStrHelper.add("RroObject", rroObj);
            }
            if (bandwidth instanceof PcepBandwidthObjectVer1) {
                toStrHelper.add("bandwidthObject", bandwidth);
            }
            return toStrHelper.toString();
        }
    }

    //SRP Object
    private PcepSrpObject srpObject;
    //LSP Object
    private PcepLspObject lspObject;
    //PcepMsgPath
    private PcepStateReport.PcepMsgPath msgPath;

    /**
     * Constructor to reset objects.
     */
    public PcepStateReportVer1() {
        this.srpObject = null;
        this.lspObject = null;
        this.msgPath = null;
    }

    public PcepStateReportVer1(PcepSrpObject srpObject, PcepLspObject lspObject, PcepStateReport.PcepMsgPath msgPath) {
        this.srpObject = srpObject;
        this.lspObject = lspObject;
        this.msgPath = msgPath;
    }

    @Override
    public PcepSrpObject getSrpObject() {
        return srpObject;
    }

    @Override
    public PcepLspObject getLspObject() {
        return lspObject;
    }

    @Override
    public PcepStateReport.PcepMsgPath getMsgPath() {
        return msgPath;
    }

    @Override
    public void setSrpObject(PcepSrpObject srpObj) {
        this.srpObject = srpObj;
    }

    @Override
    public void setLspObject(PcepLspObject lspObject) {
        this.lspObject = lspObject;
    }

    @Override
    public void setMsgPath(PcepStateReport.PcepMsgPath msgPath) {
        this.msgPath = msgPath;
    }

    /**
     * Builder class for PCEP state report.
     */
    public static class Builder implements PcepStateReport.Builder {

        private boolean bIsSRPObjectSet = false;
        private boolean bIsLSPObjectSet = false;
        private boolean bIsPcepMsgPathSet = false;

        //PCEP SRP Object
        private PcepSrpObject srpObject;
        //PCEP LSP Object
        private PcepLspObject lspObject;
        //PCEP Attribute list
        private PcepStateReport.PcepMsgPath msgPath;

        @Override
        public PcepStateReport build() throws PcepParseException {

            //PCEP SRP Object
            PcepSrpObject srpObject = null;
            //PCEP LSP Object
            PcepLspObject lspObject = null;
            //PCEP Attribute list
            PcepStateReport.PcepMsgPath msgPath = null;

            if (this.bIsSRPObjectSet) {
                srpObject = this.srpObject;
            }

            if (!this.bIsLSPObjectSet) {
                throw new PcepParseException(" LSP Object NOT Set while building PcepStateReport.");
            } else {
                lspObject = this.lspObject;
            }
            if (!this.bIsPcepMsgPathSet) {
                throw new PcepParseException(" Message Path NOT Set while building PcepStateReport.");
            } else {
                msgPath = this.msgPath;
            }

            return new PcepStateReportVer1(srpObject, lspObject, msgPath);
        }

        @Override
        public PcepSrpObject getSrpObject() {
            return this.srpObject;
        }

        @Override
        public PcepLspObject getLspObject() {
            return this.lspObject;
        }

        @Override
        public PcepStateReport.PcepMsgPath getMsgPath() {
            return this.msgPath;
        }

        @Override
        public Builder setSrpObject(PcepSrpObject srpobj) {
            this.srpObject = srpobj;
            this.bIsSRPObjectSet = true;
            return this;
        }

        @Override
        public Builder setLspObject(PcepLspObject lspObject) {
            this.lspObject = lspObject;
            this.bIsLSPObjectSet = true;
            return this;
        }

        @Override
        public Builder setMsgPath(PcepStateReport.PcepMsgPath msgPath) {
            this.msgPath = msgPath;
            this.bIsPcepMsgPathSet = true;
            return this;
        }
    }

    @Override
    public String toString() {
        ToStringHelper toStrHelper = MoreObjects.toStringHelper(getClass());

        if (this.srpObject instanceof PcepSrpObject) {
            toStrHelper.add("SrpObject", srpObject);
        }
        if (this.lspObject instanceof PcepLspObject) {
            toStrHelper.add("LspObject", lspObject);
        }
        if (this.msgPath instanceof PcepStateReport.PcepMsgPath) {
            toStrHelper.add("MsgPath", msgPath);
        }
        return toStrHelper.toString();
    }
}