/*
 * 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.PcepAttribute;
import org.onosproject.pcepio.protocol.PcepBandwidthObject;
import org.onosproject.pcepio.protocol.PcepIroObject;
import org.onosproject.pcepio.protocol.PcepLspaObject;
import org.onosproject.pcepio.protocol.PcepMetricObject;
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;

/**
 * Provides PCEP Attribute List.
 */
public class PcepAttributeVer1 implements PcepAttribute {

    /* Reference : RFC5440
     *  where:
     *      <attribute-list>                  ::=[<LSPA>]
     *                                           [<BANDWIDTH>]
     *                                           [<metric-list>]
     *                                           [<IRO>]
     *
     *      <metric-list>                     ::=<METRIC>[<metric-list>]
     */
    protected static final Logger log = LoggerFactory.getLogger(PcepAttributeVer1.class);

    public static final int OBJECT_HEADER_LENGTH = 4;

    //PCEP LSPA Object
    private PcepLspaObject lspaObject;
    private boolean isLspaObjectSet;

    //PCEP Bandwidth Object
    private PcepBandwidthObject bandwidthObject;
    private boolean isBandwidthObjectSet;

    //PCEP Metric list
    private LinkedList<PcepMetricObject> llMetricList;
    private boolean isMetricListSet;

    //PCEP IRO object
    private PcepIroObject iroObject;
    private boolean isIroObjectSet;

    /**
     * Default constructor to initialize member variables.
     */
    public PcepAttributeVer1() {

        lspaObject = null;
        bandwidthObject = null;
        llMetricList = null;
        iroObject = null;
        this.isLspaObjectSet = false;
        this.isBandwidthObjectSet = false;
        this.isMetricListSet = false;
        this.isIroObjectSet = false;
    }

    /**
     * Constructor to initialize all parameters for PCEP attribute.
     *
     * @param lspaObject         PCEP lspa Object.
     * @param bandwidthObject    PCEP bandwidth object.
     * @param llMetricList       list of PCEP metric objects.
     * @param iroObject          PCEP iro object.
     */
    public PcepAttributeVer1(PcepLspaObject lspaObject, PcepBandwidthObject bandwidthObject,
            LinkedList<PcepMetricObject> llMetricList, PcepIroObject iroObject) {

        this.lspaObject = lspaObject;
        this.bandwidthObject = bandwidthObject;
        this.llMetricList = llMetricList;
        this.iroObject = iroObject;
        if (lspaObject == null) {
            this.isLspaObjectSet = false;
        } else {
            this.isLspaObjectSet = true;
        }
        if (bandwidthObject == null) {
            this.isBandwidthObjectSet = false;
        } else {
            this.isBandwidthObjectSet = true;
        }
        if (llMetricList == null) {
            this.isMetricListSet = false;
        } else {
            this.isMetricListSet = true;
        }
        if (iroObject == null) {
            this.isIroObjectSet = false;
        } else {
            this.isIroObjectSet = true;
        }
    }

    /**
     * constructor to initialize bandwidthObject.
     *
     * @param bandwidthObject bandwidth object
     */
    public PcepAttributeVer1(PcepBandwidthObject bandwidthObject) {
        this.isLspaObjectSet = false;

        this.bandwidthObject = bandwidthObject;
        this.isBandwidthObjectSet = true;

        this.isMetricListSet = false;

        this.isIroObjectSet = false;
    }

    /**
     * Parse list for MeticObject.
     *
     * @param cb of type channel buffer
     * @return true if parsing metric list is success
     * @throws PcepParseException when a non metric object is received
     */
    public boolean parseMetricList(ChannelBuffer cb) throws PcepParseException {

        if (null == llMetricList) {
            llMetricList = new LinkedList<PcepMetricObject>();
        }

        PcepMetricObject metriclist;

        //caller should verify for metric object
        byte yObjClass = PcepMetricObjectVer1.METRIC_OBJ_CLASS;
        byte yObjType = PcepMetricObjectVer1.METRIC_OBJ_TYPE;

        while ((yObjClass == PcepMetricObjectVer1.METRIC_OBJ_CLASS)
                && (yObjType == PcepMetricObjectVer1.METRIC_OBJ_TYPE)) {

            metriclist = PcepMetricObjectVer1.read(cb);
            llMetricList.add(metriclist);
            yObjClass = 0;
            yObjType = 0;

            if (cb.readableBytes() > OBJECT_HEADER_LENGTH) {
                cb.markReaderIndex();
                PcepObjectHeader tempObjHeader = PcepObjectHeader.read(cb);
                cb.resetReaderIndex();
                yObjClass = tempObjHeader.getObjClass();
                yObjType = tempObjHeader.getObjType();
            }
        }
        return true;
    }

    /**
     * Reads lspa , bandwidth , Metriclist and Iro objects and sets the objects.
     *
     * @param cb of type channel buffer
     * @return instance of Pcep Attribute
     * @throws PcepParseException while parsing Pcep Attributes from channel buffer
     */

    public static PcepAttribute read(ChannelBuffer cb) throws PcepParseException {
        if (cb.readableBytes() < OBJECT_HEADER_LENGTH) {
            return null;
        }
        //check whether any pcep attribute is present
        cb.markReaderIndex();
        PcepObjectHeader tempObjHeader = PcepObjectHeader.read(cb);
        cb.resetReaderIndex();
        byte yObjClass = tempObjHeader.getObjClass();

        if (PcepLspaObjectVer1.LSPA_OBJ_CLASS != yObjClass && PcepBandwidthObjectVer1.BANDWIDTH_OBJ_CLASS != yObjClass
                && PcepMetricObjectVer1.METRIC_OBJ_CLASS != yObjClass && PcepIroObjectVer1.IRO_OBJ_CLASS != yObjClass) {
            //No PCEP attribute is present
            return null;
        }

        PcepAttributeVer1 pcepAttribute = new PcepAttributeVer1();

        //If LSPA present then store it.LSPA is optional
        if (yObjClass == PcepLspaObjectVer1.LSPA_OBJ_CLASS) {
            pcepAttribute.setLspaObject(PcepLspaObjectVer1.read(cb));
            yObjClass = checkNextObject(cb);
        }

        //If BANDWIDTH present then store it.BANDWIDTH is optional
        if (yObjClass == PcepBandwidthObjectVer1.BANDWIDTH_OBJ_CLASS) {
            pcepAttribute.setBandwidthObject(PcepBandwidthObjectVer1.read(cb));
            yObjClass = checkNextObject(cb);
        }

        //If Metric list present then store it.MetricList is optional
        if (yObjClass == PcepMetricObjectVer1.METRIC_OBJ_CLASS) {
            pcepAttribute.parseMetricList(cb);
            yObjClass = checkNextObject(cb);
        }

        //If IRO present then store it.IRO is optional
        if (yObjClass == PcepIroObjectVer1.IRO_OBJ_CLASS) {
            pcepAttribute.setIroObject(PcepIroObjectVer1.read(cb));
        }

        PcepLspaObject lspaObject = pcepAttribute.getLspaObject();
        PcepBandwidthObject bandwidthObject = pcepAttribute.getBandwidthObject();
        LinkedList<PcepMetricObject> metriclist = pcepAttribute.llMetricList;
        PcepIroObject iroObject = pcepAttribute.getIroObject();

        return new PcepAttributeVer1(lspaObject, bandwidthObject, metriclist, iroObject);
    }

    /**
     * Checks whether there is a more object or not.
     *
     * @param cb of type channel buffer
     * @return instance of object header
     */
    private static byte checkNextObject(ChannelBuffer cb) {
        if (cb.readableBytes() < OBJECT_HEADER_LENGTH) {
            return 0;
        }
        cb.markReaderIndex();
        PcepObjectHeader tempObjHeader = PcepObjectHeader.read(cb);
        cb.resetReaderIndex();
        return tempObjHeader.getObjClass();
    }

    @Override
    public int write(ChannelBuffer cb) throws PcepParseException {
        int iLenStartIndex = cb.writerIndex();
        //PCEP LSPA object is optional
        if (this.isLspaObjectSet) {
            this.lspaObject.write(cb);
        }

        //PCEP BANDWIDTH object is optional
        if (this.isBandwidthObjectSet) {
            this.bandwidthObject.write(cb);
        }

        //PCEP Metric list is optional
        if (this.isMetricListSet) {
            ListIterator<PcepMetricObject> listIterator = this.llMetricList.listIterator();
            while (listIterator.hasNext()) {
                listIterator.next().write(cb);
            }
        }

        //PCEP  IRO object is optional
        if (this.isIroObjectSet) {
            this.iroObject.write(cb);
        }
        return cb.writerIndex() - iLenStartIndex;
    }

    @Override
    public PcepLspaObject getLspaObject() {
        return lspaObject;
    }

    @Override
    public PcepBandwidthObject getBandwidthObject() {
        return bandwidthObject;
    }

    @Override
    public LinkedList<PcepMetricObject> getMetricObjectList() {
        return llMetricList;
    }

    @Override
    public PcepIroObject getIroObject() {
        return iroObject;
    }

    @Override
    public void setBandwidthObject(PcepBandwidthObject bandwidthObject) {
        this.isBandwidthObjectSet = true;
        this.bandwidthObject = bandwidthObject;
    }

    @Override
    public void setMetricObjectList(LinkedList<PcepMetricObject> llMetricList) {
        this.isMetricListSet = true;
        this.llMetricList = llMetricList;

    }

    @Override
    public void setLspaObject(PcepLspaObject lspaObject) {
        this.isLspaObjectSet = true;
        this.lspaObject = lspaObject;
    }

    @Override
    public void setIroObject(PcepIroObject iroObject) {
        this.isIroObjectSet = true;
        this.iroObject = iroObject;
    }

    /**
     * Builder class for PCEP attributes.
     */
    public static class Builder implements PcepAttribute.Builder {

        //PCEP LSPA Object
        private PcepLspaObject lspaObject;
        private boolean isLspaObjectSet;

        //PCEP BANDWIDTH Object
        private PcepBandwidthObject bandwidthObject;
        private boolean isBandwidthObjectSet;

        //PCEP Metric list
        private LinkedList<PcepMetricObject> llMetricList;
        private boolean isMetricListSet;

        //PCEP IRO object
        private PcepIroObject iroObject;
        private boolean isIroObjectSet;

        @Override
        public PcepAttribute build() {

            //PCEP LSPA Object
            PcepLspaObject lspaObject = null;

            //PCEP BANDWIDTH Object
            PcepBandwidthObject bandwidthObject = null;

            //PCEP Metric list
            LinkedList<PcepMetricObject> llMetricList = null;

            //PCEP IRO object
            PcepIroObject iroObject = null;

            if (this.isLspaObjectSet) {
                lspaObject = this.lspaObject;
            }
            if (this.isBandwidthObjectSet) {
                bandwidthObject = this.bandwidthObject;
            }
            if (this.isMetricListSet) {
                llMetricList = this.llMetricList;
            }
            if (this.isIroObjectSet) {
                iroObject = this.iroObject;
            }
            return new PcepAttributeVer1(lspaObject, bandwidthObject, llMetricList, iroObject);
        }

        @Override
        public PcepLspaObject getLspaObject() {
            return this.lspaObject;
        }

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

        @Override
        public LinkedList<PcepMetricObject> getMetricObjectList() {
            return this.llMetricList;
        }

        @Override
        public PcepIroObject getIroObject() {
            return this.iroObject;
        }

        @Override
        public Builder setBandwidthObject(PcepBandwidthObject bandwidthObject) {
            this.isBandwidthObjectSet = true;
            this.bandwidthObject = bandwidthObject;
            return this;
        }

        @Override
        public Builder setMetricObjectList(LinkedList<PcepMetricObject> llMetricList) {
            this.isMetricListSet = true;
            this.llMetricList = llMetricList;
            return this;
        }

        @Override
        public Builder setLspaObject(PcepLspaObject lspaObject) {
            this.isLspaObjectSet = true;
            this.lspaObject = lspaObject;
            return this;
        }

        @Override
        public Builder setIroObject(PcepIroObject iroObject) {
            this.isIroObjectSet = true;
            this.iroObject = iroObject;
            return this;
        }
    }

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

        if (lspaObject instanceof PcepLspaObject) {
            toStrHelper.add("lspaObject", lspaObject);
        }
        if (bandwidthObject instanceof PcepBandwidthObject) {
            toStrHelper.add("bandwidthObject", bandwidthObject);
        }
        if (llMetricList instanceof PcepMetricObject) {
            toStrHelper.add("MetricObjectList", llMetricList);
        }
        if (iroObject instanceof PcepIroObject) {
            toStrHelper.add("IroObject", iroObject);
        }
        return toStrHelper.toString();
    }
}