/*
 * 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.ListIterator;

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

import com.google.common.base.MoreObjects;

/**
 * Provides PCEP Error Object.
 */
public class PcepErrorObjectVer1 implements PcepErrorObject {

    /*
    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    | Object-Class  |   OT  |Res|P|I|   Object Length (bytes)       |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |   Reserved    |      Flags    |   Error-Type  |  Error-value  |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                                                               |
    //                         Optional TLVs                       //
    |                                                               |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     */
    private static final Logger log = LoggerFactory.getLogger(PcepErrorObjectVer1.class);

    public static final byte ERROR_OBJ_TYPE = 1;
    public static final byte ERROR_OBJ_CLASS = 13;
    public static final byte ERROR_OBJECT_VERSION = 1;
    //ERROR_OBJ_MINIMUM_LENGTH = CommonHeaderLen(4)+ErrorObjectHeaderLen(4)
    public static final short ERROR_OBJ_MINIMUM_LENGTH = 8;
    public static final int OBJECT_HEADER_LENGTH = 4;

    public static final PcepObjectHeader DEFAULT_ERROR_OBJECT_HEADER = new PcepObjectHeader(ERROR_OBJ_CLASS,
            ERROR_OBJ_TYPE, PcepObjectHeader.REQ_OBJ_OPTIONAL_PROCESS, PcepObjectHeader.RSP_OBJ_PROCESSED,
            ERROR_OBJ_MINIMUM_LENGTH);

    private PcepObjectHeader errorObjHeader;
    private byte errorType;
    private byte errorValue;
    private LinkedList<PcepValueType> optionalTlv; // Optional TLV

    /**
     * Constructor to initialize variables.
     *
     * @param errorObjHeader ERROR Object header
     * @param errorType Error Type
     * @param errorValue Error Value
     * @param optionalTlv list of optional TLV
     */

    public PcepErrorObjectVer1(PcepObjectHeader errorObjHeader, byte errorType, byte errorValue,
            LinkedList<PcepValueType> optionalTlv) {
        this.errorObjHeader = errorObjHeader;
        this.errorType = errorType;
        this.errorValue = errorValue;
        this.optionalTlv = optionalTlv;
    }

    /**
     * sets Object Header.
     *
     * @param obj Error-Object header
     */
    public void setLspObjHeader(PcepObjectHeader obj) {
        this.errorObjHeader = obj;
    }

    @Override
    public void setErrorType(byte errorType) {
        this.errorType = errorType;
    }

    @Override
    public void setErrorValue(byte errorValue) {
        this.errorValue = errorValue;
    }

    /**
     * returns object header.
     *
     * @return errorObjHeader Error-Object header
     */
    public PcepObjectHeader getErrorObjHeader() {
        return this.errorObjHeader;
    }

    @Override
    public int getErrorType() {
        return this.errorType;
    }

    @Override
    public byte getErrorValue() {
        return this.errorValue;
    }

    @Override
    public LinkedList<PcepValueType> getOptionalTlv() {
        return this.optionalTlv;
    }

    @Override
    public void setOptionalTlv(LinkedList<PcepValueType> optionalTlv) {
        this.optionalTlv = optionalTlv;
    }

    /**
     * Reads from channel buffer and returns object of PcepErrorObject.
     *
     * @param cb of channel buffer.
     * @return object of PCEP-ERROR-OBJECT
     */
    public static PcepErrorObject read(ChannelBuffer cb) {

        PcepObjectHeader errorObjHeader;
        byte errorType;
        byte errorValue;
        LinkedList<PcepValueType> optionalTlv;

        errorObjHeader = PcepObjectHeader.read(cb);

        //take only ErrorObject buffer.
        ChannelBuffer tempCb = cb.readBytes(errorObjHeader.getObjLen() - OBJECT_HEADER_LENGTH);
        tempCb.readByte(); //ignore Reserved
        tempCb.readByte(); //ignore Flags
        errorType = tempCb.readByte();
        errorValue = tempCb.readByte();

        optionalTlv = parseOptionalTlv(tempCb);

        return new PcepErrorObjectVer1(errorObjHeader, errorType, errorValue, optionalTlv);
    }

    /**
     * returns Linked list of optional tlvs.
     *
     * @param cb channel buffer.
     * @return Linked list of optional tlvs
     */
    protected static LinkedList<PcepValueType> parseOptionalTlv(ChannelBuffer cb) {

        LinkedList<PcepValueType> llOutOptionalTlv = new LinkedList<>();

        byte[] yTemp = new byte[cb.readableBytes()];
        cb.readBytes(yTemp);

        return llOutOptionalTlv;
    }

    @Override
    public int write(ChannelBuffer cb) throws PcepParseException {

        //write Object header
        int objStartIndex = cb.writerIndex();

        int objLenIndex = errorObjHeader.write(cb);

        if (objLenIndex <= 0) {
            throw new PcepParseException("While writing Error Object Header.");
        }

        //write Reserved
        cb.writeByte(0);
        //write Flags
        cb.writeByte(0);
        //write ErrorType and ErrorValue
        cb.writeByte(this.errorType);
        cb.writeByte(this.errorValue);

        // Add optional TLV
        packOptionalTlv(cb);

        //Update object length now
        int length = cb.writerIndex() - objStartIndex;
        //will be helpful during print().
        errorObjHeader.setObjLen((short) length);
        // 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;
    }

    /**
     * Pack the Optional tlvs.
     *
     * @param cb channel buffer.
     * @return writer index.
     */
    protected int packOptionalTlv(ChannelBuffer cb) {

        ListIterator<PcepValueType> listIterator = optionalTlv.listIterator();
        int startIndex = cb.writerIndex();
        while (listIterator.hasNext()) {
            PcepValueType tlv = listIterator.next();

            if (tlv == null) {
                log.debug("TLV is null from OptionalTlv list");
                continue;
            }
            tlv.write(cb);
        }

        return cb.writerIndex() - startIndex;
    }

    /**
     * Builder class for PCEP error object.
     */
    public static class Builder implements PcepErrorObject.Builder {

        private boolean bIsHeaderSet = false;

        private PcepObjectHeader errorObjHeader;
        private byte errorType;
        private byte errorValue;

        private boolean bIsPFlagSet = false;
        private boolean bPFlag;

        private boolean bIsIFlagSet = false;
        private boolean bIFlag;

        private LinkedList<PcepValueType> optionalTlv = new LinkedList<>();

        @Override
        public PcepErrorObject build() {

            PcepObjectHeader errorObjHeader = this.bIsHeaderSet ? this.errorObjHeader : DEFAULT_ERROR_OBJECT_HEADER;

            if (bIsPFlagSet) {
                errorObjHeader.setPFlag(bPFlag);
            }

            if (bIsIFlagSet) {
                errorObjHeader.setIFlag(bIFlag);
            }

            return new PcepErrorObjectVer1(errorObjHeader, errorType, errorValue, optionalTlv);
        }

        @Override
        public PcepObjectHeader getErrorObjHeader() {
            return this.errorObjHeader;
        }

        @Override
        public Builder setErrorObjHeader(PcepObjectHeader obj) {
            this.errorObjHeader = obj;
            this.bIsHeaderSet = true;
            return this;
        }

        @Override
        public int getErrorType() {
            return this.errorType;
        }

        @Override
        public Builder setErrorType(byte value) {
            this.errorType = value;
            return this;
        }

        @Override
        public byte getErrorValue() {
            return this.errorValue;
        }

        @Override
        public Builder setErrorValue(byte value) {
            this.errorValue = value;
            return this;
        }

        @Override
        public Builder setOptionalTlv(LinkedList<PcepValueType> optionalTlv) {
            this.optionalTlv = optionalTlv;
            return this;
        }

        @Override
        public LinkedList<PcepValueType> getOptionalTlv() {
            return this.optionalTlv;
        }

        @Override
        public Builder setPFlag(boolean value) {
            this.bPFlag = value;
            this.bIsPFlagSet = true;
            return this;
        }

        @Override
        public Builder setIFlag(boolean value) {
            this.bIFlag = value;
            this.bIsIFlagSet = true;
            return this;
        }
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(getClass())
                .add("ObjectHeader", errorObjHeader).add("ErrorType", errorType)
                .add("ErrorValue", errorValue).add("OptionalTlv", optionalTlv).toString();
    }
}
