/*
 * 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 org.jboss.netty.buffer.ChannelBuffer;
import org.onosproject.pcepio.exceptions.PcepParseException;
import org.onosproject.pcepio.protocol.PcepErrorInfo;
import org.onosproject.pcepio.protocol.PcepErrorMsg;
import org.onosproject.pcepio.protocol.PcepErrorObject;
import org.onosproject.pcepio.protocol.PcepMessageReader;
import org.onosproject.pcepio.protocol.PcepMessageWriter;
import org.onosproject.pcepio.protocol.PcepOpenObject;
import org.onosproject.pcepio.protocol.PcepType;
import org.onosproject.pcepio.protocol.PcepVersion;
import org.onosproject.pcepio.types.ErrorObjListWithOpen;
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 Error Message.
 */
public class PcepErrorMsgVer1 implements PcepErrorMsg {

    /*
     * PCE Error message format.

       <PCErr Message>                ::= <Common Header>
                                        ( <error-obj-list> [<Open>] ) | <error>
                                          [<error-list>]

       <error-obj-list>               ::=<PCEP-ERROR>[<error-obj-list>]

       <error>                        ::=[<request-id-list> | <te-id-list>]
                                           <error-obj-list>

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

       <te-id-list>                   ::=<TE>[<te-id-list>]

       <error-list>                   ::=<error>[<error-list>]
     */

    protected static final Logger log = LoggerFactory.getLogger(PcepOpenMsgVer1.class);
    public static final byte PACKET_VERSION = 1;
    public static final int PACKET_MINIMUM_LENGTH = 12;
    public static final PcepType MSG_TYPE = PcepType.ERROR;

    //Below either one should be present.
    private ErrorObjListWithOpen errObjListWithOpen; //optional   ( <error-obj-list> [<Open>] )
    private PcepErrorInfo errInfo; //optional     <error> [<error-list>]

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

    /**
     * constructor to initialize variables.
     */
    public PcepErrorMsgVer1() {
        errObjListWithOpen = null;
        errInfo = null;
    }

    /**
     * Constructor to initialize variables.
     *
     * @param errObjListWithOpen error-object-list with open object
     * @param errInfo error information
     */
    public PcepErrorMsgVer1(ErrorObjListWithOpen errObjListWithOpen, PcepErrorInfo errInfo) {
        this.errObjListWithOpen = errObjListWithOpen;
        this.errInfo = errInfo;
    }

    /**
     * Reader class for reading PCEP error Message from channel buffer.
     */
    public static class Reader implements PcepMessageReader<PcepErrorMsg> {

        ErrorObjListWithOpen errObjListWithOpen;
        PcepErrorInfo errInfo;
        PcepObjectHeader tempObjHeader;

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

            errObjListWithOpen = null;
            errInfo = null;
            tempObjHeader = null;

            if (cb.readableBytes() < PACKET_MINIMUM_LENGTH) {
                throw new PcepParseException("Packet size is less than the minimum length.");
            }

            byte version = cb.readByte();
            version = (byte) (version >> PcepMessageVer1.SHIFT_FLAG);
            if (version != PACKET_VERSION) {
                throw new PcepParseException("Wrong version: Expected=PcepVersion.PCEP_1(1), got=" + version);
            }
            // fixed value property type == 1
            byte type = cb.readByte();
            if (type != MSG_TYPE.getType()) {
                throw new PcepParseException("Wrong type: Expected=PcepType.ERROR(6), got=" + type);
            }
            int length = cb.readShort();
            if (length < PACKET_MINIMUM_LENGTH) {
                throw new PcepParseException(
                        "Wrong length: Expected to be >= " + PACKET_MINIMUM_LENGTH + ", was: " + length);
            }

            //parse <PCErr Message>
            parsePCErrMsg(cb);

            // If other than RP or TE or PCEP-ERROR present then it is error.
            if (0 < cb.readableBytes()) {
                PcepObjectHeader tempObjHeader = PcepObjectHeader.read(cb);
                throw new PcepParseException("Unexpected Object found. Object Class : " + tempObjHeader.getObjClass());
            }

            return new PcepErrorMsgVer1(errObjListWithOpen, errInfo);
        }

        /**
         * Parsing PCErr Message.
         *
         * @param cb channel buffer.
         * @throws PcepParseException if mandatory fields are missing
         * output: this.errObjListWithOpen, this.errInfo
         */
        public void parsePCErrMsg(ChannelBuffer cb) throws PcepParseException {
            //If PCEP-ERROR list is followed by OPEN Object then store into ErrorObjListWithOpen.
            //     ( <error-obj-list> [<Open>]
            //If PCEP-ERROR list is followed by RP or TE Object then store into errInfo. <error> [<error-list>]
            //If only PCEP-ERROR list is present then store into ErrorObjListWithOpen.
            PcepObjectHeader tempObjHeader;
            LinkedList<PcepErrorObject> llErrObjList;

            if (0 >= cb.readableBytes()) {
                throw new PcepParseException("PCEP-ERROR message came with empty objects.");
            }

            //parse PCEP-ERROR list
            llErrObjList = new LinkedList<>();
            tempObjHeader = parseErrorObjectList(llErrObjList, cb);

            //check whether OPEN-OBJECT is present.
            if ((tempObjHeader != null)
                    && (tempObjHeader.getObjClass() == PcepOpenObjectVer1.OPEN_OBJ_CLASS)) {

                if (llErrObjList.isEmpty()) {
                    throw new PcepParseException("<error-obj-list> should be present if OPEN-OBJECT exists");
                }

                PcepOpenObject pcepOpenObj = PcepOpenObjectVer1.read(cb);
                this.errObjListWithOpen = new ErrorObjListWithOpen(llErrObjList, pcepOpenObj);

            } else if ((tempObjHeader != null) //check whether RP or TE Object is present.
                    && ((tempObjHeader.getObjClass() == PcepRPObjectVer1.RP_OBJ_CLASS)
                            || (tempObjHeader.getObjClass() == PcepTEObjectVer1.TE_OBJ_CLASS))) {

                this.errInfo = new PcepErrorInfoVer1(null, null, llErrObjList);
                this.errInfo.read(cb);

            } else if (!llErrObjList.isEmpty()) {
                //If only PCEP-ERROR list is present then store it in errObjListWithOpen.
                this.errObjListWithOpen = new ErrorObjListWithOpen(llErrObjList);
            } else {
                throw new PcepParseException("Empty PCEP-ERROR message.");
            }
        }

        /**
         * Parse error-obj-list.
         *
         * @param llErrObjList error object list output
         * @param cb channel buffer input
         * @throws PcepParseException if mandatory fields are missing
         * @return error object header
         */
        public PcepObjectHeader parseErrorObjectList(LinkedList<PcepErrorObject> llErrObjList, ChannelBuffer cb)
                throws PcepParseException {
            PcepObjectHeader tempObjHeader = null;

            while (0 < cb.readableBytes()) {
                cb.markReaderIndex();
                tempObjHeader = PcepObjectHeader.read(cb);
                cb.resetReaderIndex();
                if (tempObjHeader.getObjClass() == PcepErrorObjectVer1.ERROR_OBJ_CLASS) {
                    llErrObjList.add(PcepErrorObjectVer1.read(cb));
                } else {
                    break;
                }
            }
            return tempObjHeader;
        }
    }

    /**
     * Builder class for PCEP error message.
     */
    public static class Builder implements PcepErrorMsg.Builder {
        // Pcep error message fields

        private ErrorObjListWithOpen errObjListWithOpen = null; //optional   ( <error-obj-list> [<Open>] )
        private PcepErrorInfo errInfo = null; //optional     <error> [<error-list>]

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

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

        @Override
        public PcepErrorMsg build() {
            return new PcepErrorMsgVer1(this.errObjListWithOpen, this.errInfo);
        }

        @Override
        public ErrorObjListWithOpen getErrorObjListWithOpen() {
            return this.errObjListWithOpen;
        }

        @Override
        public Builder setErrorObjListWithOpen(ErrorObjListWithOpen errObjListWithOpen) {
            this.errObjListWithOpen = errObjListWithOpen;
            return this;
        }

        @Override
        public PcepErrorInfo getPcepErrorInfo() {
            return this.errInfo;
        }

        @Override
        public Builder setPcepErrorInfo(PcepErrorInfo errInfo) {
            this.errInfo = errInfo;
            return this;
        }
    }

    @Override
    public void writeTo(ChannelBuffer cb) throws PcepParseException {
        WRITER.write(cb, this);
    }

    public static final Writer WRITER = new Writer();

    /**
     * Writer class for writing PCEP error Message to channel buffer.
     */
    static class Writer implements PcepMessageWriter<PcepErrorMsgVer1> {
        @Override
        public void write(ChannelBuffer cb, PcepErrorMsgVer1 message) throws PcepParseException {
            int startIndex = cb.writerIndex();
            // first 3 bits set to version
            cb.writeByte((byte) (PACKET_VERSION << PcepMessageVer1.SHIFT_FLAG));
            // message type 0xC
            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(0);
            ErrorObjListWithOpen errObjListWithOpen = message.getErrorObjListWithOpen();
            PcepErrorInfo errInfo = message.getPcepErrorInfo();

            // write ( <error-obj-list> [<Open>] ) if exists.
            // otherwise write <error> [<error-list>]

            if ((errObjListWithOpen != null)
                    && (errObjListWithOpen.isErrorObjListWithOpenPresent())) {
                errObjListWithOpen.write(cb);
            } else if ((errInfo != null) && (errInfo.isErrorInfoPresent())) {
                errInfo.write(cb);
            } else {
                throw new PcepParseException("Empty PCEP-ERROR message.");
            }
            // PcepErrorMessage 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 ErrorObjListWithOpen getErrorObjListWithOpen() {
        return this.errObjListWithOpen;
    }

    @Override
    public void setErrorObjListWithOpen(ErrorObjListWithOpen errObjListWithOpen) {
        this.errObjListWithOpen = errObjListWithOpen;
    }

    @Override
    public PcepErrorInfo getPcepErrorInfo() {
        return this.errInfo;
    }

    @Override
    public void setPcepErrorInfo(PcepErrorInfo errInfo) {
        this.errInfo = errInfo;
    }

    /**
     * Return list of Error types.
     *
     * @return error types list
     */
    public LinkedList<Integer> getErrorType() {
        LinkedList<Integer> llErrorType = new LinkedList<>();
        if ((errObjListWithOpen != null)
                && (errObjListWithOpen.isErrorObjListWithOpenPresent())) {
            llErrorType = errObjListWithOpen.getErrorType();
        } else if ((errInfo != null) && (errInfo.isErrorInfoPresent())) {
            llErrorType = errInfo.getErrorType();
        }

        return llErrorType;
    }

    /**
     * Return list of Error values.
     *
     * @return error value list
     */
    public LinkedList<Integer> getErrorValue() {
        LinkedList<Integer> llErrorValue = new LinkedList<>();
        if ((errObjListWithOpen != null)
                && (errObjListWithOpen.isErrorObjListWithOpenPresent())) {
            llErrorValue = errObjListWithOpen.getErrorValue();
        } else if ((errInfo != null) && (errInfo.isErrorInfoPresent())) {
            llErrorValue = errInfo.getErrorValue();
        }

        return llErrorValue;
    }

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

        if ((errObjListWithOpen != null)
                && (errObjListWithOpen.isErrorObjListWithOpenPresent())) {
            toStrHelper.add("ErrorObjectListWithOpen", errObjListWithOpen);
        }
        if ((errInfo != null) && (errInfo.isErrorInfoPresent())) {
            toStrHelper.add("ErrorInfo", errInfo);
        }

        return toStrHelper.toString();
    }
}
