/*
 * Copyright 2015-present Open Networking Foundation
 *
 * 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.List;
import java.util.ListIterator;

import org.jboss.netty.buffer.ChannelBuffer;
import org.onosproject.pcepio.exceptions.PcepParseException;
import org.onosproject.pcepio.protocol.PcepError;
import org.onosproject.pcepio.protocol.PcepErrorObject;
import org.onosproject.pcepio.protocol.PcepRPObject;
import org.onosproject.pcepio.protocol.PcepLSObject;
import org.onosproject.pcepio.types.PcepObjectHeader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.MoreObjects;

/**
 * Provides PcepError list which contains RP or LS objects.
 * Reference: draft-dhodylee-pce-pcep-ls-01, section 8.2.
 */
public class PcepErrorVer1 implements PcepError {

    /*
           <error>::=[<request-id-list> | <ls-id-list>]
                      <error-obj-list>

           <request-id-list>::=<RP>[<request-id-list>]

           <ls-id-list>::=<LS>[<ls-id-list>]
     */

    private static final Logger log = LoggerFactory.getLogger(PcepErrorVer1.class);

    private boolean isErroInfoSet;
    //PcepErrorObject list
    private List<PcepErrorObject> errObjList;
    //PcepRPObject list
    private List<PcepRPObject> rpObjList;
    //PcepLSObject list
    private List<PcepLSObject> lsObjList;
    private boolean isLSObjListSet;

    public static final int OBJECT_HEADER_LENGTH = 4;

    /**
     * Constructor to initialize variable.
     */
    public PcepErrorVer1() {
        this.rpObjList = null;
        this.lsObjList = null;
        this.errObjList = null;
    }

    /**
     * Constructor to initialize variable.
     *
     * @param rpObjList list of PcepRPObject
     * @param lsObjList list of PcepLSObject
     * @param errObjListObjList list of PcepErrorObject
     */
    public PcepErrorVer1(List<PcepRPObject> rpObjList, List<PcepLSObject> lsObjList,
            List<PcepErrorObject> errObjListObjList) {
        this.rpObjList = rpObjList;
        this.lsObjList = lsObjList;
        this.errObjList = errObjListObjList;
    }

    /**
     * Constructor to initialize PcepError.
     *
     * @param errObjList list of PcepErrorObject
     */
    public PcepErrorVer1(List<PcepErrorObject> errObjList) {
        this.rpObjList = null;
        this.lsObjList = null;
        this.errObjList = errObjList;
    }

    @Override
    public List<PcepRPObject> getRPObjList() {
        return this.rpObjList;
    }

    @Override
    public List<PcepLSObject> getLSObjList() {
        return this.lsObjList;
    }

    @Override
    public List<PcepErrorObject> getErrorObjList() {
        return this.errObjList;
    }

    /**
     * Parse RP List from the channel buffer.
     *
     * @param cb of type channel buffer
     * @throws PcepParseException if mandatory fields are missing
     */
    public void parseRPList(ChannelBuffer cb) throws PcepParseException {
        byte yObjClass;
        byte yObjType;

        rpObjList = new LinkedList<>();

        // caller should verify for RP object
        if (cb.readableBytes() < OBJECT_HEADER_LENGTH) {
            log.debug("Unable to find RP Object");
            return;
        }

        cb.markReaderIndex();
        PcepObjectHeader tempObjHeader = PcepObjectHeader.read(cb);
        cb.resetReaderIndex();
        yObjClass = tempObjHeader.getObjClass();
        yObjType = tempObjHeader.getObjType();
        PcepRPObject rpObj;
        while ((yObjClass == PcepRPObjectVer1.RP_OBJ_CLASS) && (yObjType == PcepRPObjectVer1.RP_OBJ_TYPE)) {
            rpObj = PcepRPObjectVer1.read(cb);
            rpObjList.add(rpObj);

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

    /**
     * Parse LS List from the channel buffer.
     *
     * @param cb of type channel buffer
     * @throws PcepParseException if mandatory fields are missing
     */
    public void parseLSList(ChannelBuffer cb) throws PcepParseException {
        byte yObjClass;
        byte yObjType;

        lsObjList = new LinkedList<>();

        // caller should verify for LS object
        if (cb.readableBytes() < OBJECT_HEADER_LENGTH) {
            log.debug("Unable to find LS Object");
            return;
        }

        cb.markReaderIndex();
        PcepObjectHeader tempObjHeader = PcepObjectHeader.read(cb);
        cb.resetReaderIndex();
        yObjClass = tempObjHeader.getObjClass();
        yObjType = tempObjHeader.getObjType();
        PcepLSObject lsObj;
        while ((yObjClass == PcepLSObjectVer1.LS_OBJ_CLASS) && ((yObjType == PcepLSObjectVer1.LS_OBJ_TYPE_NODE_VALUE)
                || (yObjType == PcepLSObjectVer1.LS_OBJ_TYPE_LINK_VALUE))) {
            lsObj = PcepLSObjectVer1.read(cb);
            lsObjList.add(lsObj);

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

    /**
     * parseErrObjList from the channel buffer.
     *
     * @param cb of type channel buffer
     * @throws PcepParseException if mandatory fields are missing
     */
    public void parseErrObjList(ChannelBuffer cb) throws PcepParseException {
        byte yObjClass;
        byte yObjType;
        boolean bIsErrorObjFound = false;

        errObjList = new LinkedList<>();

        // caller should verify for RP object
        if (cb.readableBytes() < OBJECT_HEADER_LENGTH) {
            throw new PcepParseException("Unable to find PCEP-ERROR Object");
        }

        cb.markReaderIndex();
        PcepObjectHeader tempObjHeader = PcepObjectHeader.read(cb);
        cb.resetReaderIndex();
        yObjClass = tempObjHeader.getObjClass();
        yObjType = tempObjHeader.getObjType();
        PcepErrorObject errorObject;
        while ((yObjClass == PcepErrorObjectVer1.ERROR_OBJ_CLASS) && (yObjType == PcepErrorObjectVer1.ERROR_OBJ_TYPE)) {
            errorObject = PcepErrorObjectVer1.read(cb);
            errObjList.add(errorObject);
            bIsErrorObjFound = true;

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

        if (!bIsErrorObjFound) {
            throw new PcepParseException("At least one PCEP-ERROR Object should be present.");
        }
    }

    /**
     * Reads the byte stream of PcepError from channel buffer.
     *
     * @param cb of type channel buffer
     * @return PcepError error part of PCEP-ERROR
     * @throws PcepParseException if mandatory fields are missing
     */
    public static PcepErrorVer1 read(ChannelBuffer cb) throws PcepParseException {
        if (cb.readableBytes() < OBJECT_HEADER_LENGTH) {
            throw new PcepParseException("Unknown Object");
        }

        PcepErrorVer1 pcepError = new PcepErrorVer1();
        // check whether any PCEP Error Info is present
        cb.markReaderIndex();
        PcepObjectHeader tempObjHeader = PcepObjectHeader.read(cb);
        cb.resetReaderIndex();
        byte yObjClass = tempObjHeader.getObjClass();

        //If RPlist present then store it.RPList and LSList are optional
        if (yObjClass == PcepRPObjectVer1.RP_OBJ_CLASS) {
            log.debug("RP_LIST");
            pcepError.parseRPList(cb);
            yObjClass = checkNextObject(cb);
        } else if (yObjClass == PcepLSObjectVer1.LS_OBJ_CLASS) {
            log.debug("LS_LIST");
            pcepError.parseLSList(cb);
            yObjClass = checkNextObject(cb);
        }

        if (yObjClass == PcepErrorObjectVer1.ERROR_OBJ_CLASS) {
            log.debug("PCEP-ERROR obj list");
            pcepError.parseErrObjList(cb);
            yObjClass = checkNextObject(cb);
        }

        return pcepError;
    }

    /**
     * Checks Next Object.
     *
     * @param cb of type channel buffer.
     * @return object type class.
     */
    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();
    }

    /**
     * Writes the byte stream of PCEP error to the channel buffer.
     *
     * @param cb of type channel buffer
     * @return object length index
     * @throws PcepParseException if mandatory fields are missing
     */
    @Override
    public int write(ChannelBuffer cb) throws PcepParseException {
        int iLenStartIndex = cb.writerIndex();

        // RPlist is optional
        if (this.isErroInfoSet) {
            ListIterator<PcepRPObject> rpObjlistIterator = this.rpObjList.listIterator();
            while (rpObjlistIterator.hasNext()) {
                rpObjlistIterator.next().write(cb);
            }
        }

        // LSlist is optional
        if (this.isLSObjListSet) {
            ListIterator<PcepLSObject> teObjlistIterator = this.lsObjList.listIterator();
            while (teObjlistIterator.hasNext()) {
                teObjlistIterator.next().write(cb);
            }
        }
        //ErrList is mandatory
        ListIterator<PcepErrorObject> errlistIterator = this.errObjList.listIterator();
        while (errlistIterator.hasNext()) {
            errlistIterator.next().write(cb);
        }

        return cb.writerIndex() - iLenStartIndex;
    }

    /**
     * Builder for error part of PCEP-ERROR.
     */
    public static class Builder implements PcepError.Builder {

        private List<PcepRPObject> rpObjList;
        private List<PcepLSObject> lsObjList;
        private List<PcepErrorObject> errObjList;

        @Override
        public PcepError build() {
            return new PcepErrorVer1(rpObjList, lsObjList, errObjList);
        }

        @Override
        public List<PcepRPObject> getRPObjList() {
            return this.rpObjList;
        }

        @Override
        public Builder setRPObjList(List<PcepRPObject> rpObjList) {
            this.rpObjList = rpObjList;
            return this;
        }

        @Override
        public List<PcepLSObject> getLSObjList() {
            return this.lsObjList;
        }

        @Override
        public Builder setLSObjList(List<PcepLSObject> lsObjList) {
            this.lsObjList = lsObjList;
            return this;
        }

        @Override
        public List<PcepErrorObject> getErrorObjList() {
            return this.errObjList;
        }

        @Override
        public Builder setErrorObjList(List<PcepErrorObject> errObjList) {
            this.errObjList = errObjList;
            return this;
        }

    }

    @Override
    public void setRPObjList(List<PcepRPObject> rpObjList) {
        this.rpObjList = rpObjList;
    }

    @Override
    public void setLSObjList(List<PcepLSObject> lsObjList) {
        this.lsObjList = lsObjList;
    }

    @Override
    public void setErrorObjList(List<PcepErrorObject> errObjList) {
        this.errObjList = errObjList;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(getClass())
                .omitNullValues()
                .add("RpObjectList", rpObjList)
                .add("LsObjectList", lsObjList)
                .add("ErrorObjectList", errObjList)
                .toString();
    }
}
