/*
 * 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.PcepLabelRange;
import org.onosproject.pcepio.protocol.PcepLabelRangeObject;
import org.onosproject.pcepio.protocol.PcepSrpObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.MoreObjects;

/**
 * Provides PCEP Label Range.
 */
public class PcepLabelRangeVer1 implements PcepLabelRange {

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

    /*
        <label-range> ::= <SRP>
                          <labelrange-list>
        Where
                <labelrange-list>::=<LABEL-RANGE>[<labelrange-list>]
     */

    // PCEP SRP Object
    private PcepSrpObject srpObject;
    //<labelrange-list> of type PcepLabelRangeObject.
    private LinkedList<PcepLabelRangeObject> llLabelRangeList;

    /**
     * Default Constructor.
     */
    public PcepLabelRangeVer1() {
        srpObject = null;
        llLabelRangeList = null;
    }

    /**
     * Constructor to initialize objects.
     *
     * @param srpObj PCEP Srp object.
     * @param llLabelRangeList list of PcepLabelRangeObject.
     */
    PcepLabelRangeVer1(PcepSrpObject srpObj, LinkedList<PcepLabelRangeObject> llLabelRangeList) {
        this.srpObject = srpObj;
        this.llLabelRangeList = llLabelRangeList;
    }

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

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

    }

    @Override
    public LinkedList<PcepLabelRangeObject> getLabelRangeList() {
        return llLabelRangeList;
    }

    @Override
    public void setLabelRangeList(LinkedList<PcepLabelRangeObject> ll) {
        this.llLabelRangeList = ll;
    }

    /**
     * Reads channel buffer and returns object of PcepLabelRange.
     *
     * @param cb of type channel buffer.
     * @return object of PcepLabelRange
     * @throws PcepParseException when fails to read from channel buffer
     */
    public static PcepLabelRange read(ChannelBuffer cb) throws PcepParseException {

        //parse and store SRP mandatory object
        PcepSrpObject srpObj = null;
        srpObj = PcepSrpObjectVer1.read(cb);
        if (srpObj == null) {
            throw new PcepParseException("Exception while parsing srp object");
        }

        LinkedList<PcepLabelRangeObject> llLabelRangeList = new LinkedList<PcepLabelRangeObject>();
        boolean bFoundLabelRangeObj = false;
        while (0 < cb.readableBytes()) {
            //parse and store <labelrange-list>
            PcepLabelRangeObject lrObj;
            lrObj = PcepLabelRangeObjectVer1.read(cb);
            if (lrObj == null) {
                throw new PcepParseException("Exception while parsing label range object");
            } else {
                llLabelRangeList.add(lrObj);
                bFoundLabelRangeObj = true;
            }
        }

        if (!bFoundLabelRangeObj) {
            throw new PcepParseException("At least one LABEL-RANGE MUST be present.");
        }
        return new PcepLabelRangeVer1(srpObj, llLabelRangeList);
    }

    @Override
    public int write(ChannelBuffer cb) throws PcepParseException {
        //write Object header
        int objStartIndex = cb.writerIndex();

        //write <SRP>
        int objLenIndex = srpObject.write(cb);

        if (objLenIndex <= 0) {
            throw new PcepParseException("bjectLength is " + objLenIndex);
        }

        //write <labelrange-list>
        ListIterator<PcepLabelRangeObject> listIterator = llLabelRangeList.listIterator();
        while (listIterator.hasNext()) {
            listIterator.next().write(cb);
        }

        //Update object length now
        int length = cb.writerIndex() - objStartIndex;
        // As per RFC the length of object should be
        // multiples of 4
        int pad = length % 4;
        if (pad != 0) {
            pad = 4 - pad;
            for (int i = 0; i < pad; i++) {
                cb.writeByte((byte) 0);
            }
            length = length + pad;
        }
        cb.setShort(objLenIndex, (short) length);
        return length;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(getClass()).add("srpObject", srpObject)
                .add("LabelRangeList", llLabelRangeList).toString();
    }
}
