/*
 * 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.PcepLabelObject;
import org.onosproject.pcepio.types.NexthopIPv4addressTlv;
import org.onosproject.pcepio.types.NexthopIPv6addressTlv;
import org.onosproject.pcepio.types.NexthopUnnumberedIPv4IDTlv;
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 label object.
 */
public class PcepLabelObjectVer1 implements PcepLabelObject {

    /*
     *   ref : draft-zhao-pce-pcep-extension-for-pce-controller-03, section : 7.3.

    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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |          Reserved            |              Flags           |O|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                 Label                 |     Reserved          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               |
   //                        Optional TLV                         //
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     The LABEL Object format
     */
    protected static final Logger log = LoggerFactory.getLogger(PcepLspObjectVer1.class);

    public static final byte LABEL_OBJ_TYPE = 1;
    public static final byte LABEL_OBJ_CLASS = (byte) 225;
    public static final byte LABEL_OBJECT_VERSION = 1;
    public static final byte OBJECT_HEADER_LENGTH = 4;
    public static final boolean DEFAULT_OFLAG = false;

    // LSP_OBJ_MINIMUM_LENGTH = CommonHeaderLen(4)+ LspObjectHeaderLen(8)
    public static final short LABEL_OBJ_MINIMUM_LENGTH = 12;

    public static final int OFLAG_SET = 1;
    public static final int SHIFT_LABEL = 12;
    public static final int OFLAG_RESET = 0;
    public static final int MINIMUM_COMMON_HEADER_LENGTH = 4;

    static final PcepObjectHeader DEFAULT_LABEL_OBJECT_HEADER = new PcepObjectHeader(LABEL_OBJ_CLASS, LABEL_OBJ_TYPE,
            PcepObjectHeader.REQ_OBJ_OPTIONAL_PROCESS, PcepObjectHeader.RSP_OBJ_PROCESSED, LABEL_OBJ_MINIMUM_LENGTH);

    private PcepObjectHeader labelObjHeader;
    private boolean oBit;
    private int label;
    // Optional TLV
    private LinkedList<PcepValueType> optionalTlv;

    /**
     * Constructor to initialize parameters for PCEP label object.
     *
     * @param labelObjHeader label object header
     * @param oBit O flag
     * @param label label
     * @param optionalTlv list of optional tlvs
     */
    public PcepLabelObjectVer1(PcepObjectHeader labelObjHeader, boolean oBit, int label,
            LinkedList<PcepValueType> optionalTlv) {
        this.labelObjHeader = labelObjHeader;
        this.oBit = oBit;
        this.label = label;
        this.optionalTlv = optionalTlv;
    }

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

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

    @Override
    public boolean getOFlag() {
        return this.oBit;
    }

    @Override
    public void setOFlag(boolean value) {
        this.oBit = value;
    }

    @Override
    public int getLabel() {
        return this.label;
    }

    @Override
    public void setLabel(int value) {
        this.label = value;
    }

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

        PcepObjectHeader labelObjHeader;

        boolean oBit;
        int label;

        // Optional TLV
        LinkedList<PcepValueType> optionalTlv = new LinkedList<>();
        labelObjHeader = PcepObjectHeader.read(cb);

        //take only LspObject buffer.
        ChannelBuffer tempCb = cb.readBytes(labelObjHeader.getObjLen() - OBJECT_HEADER_LENGTH);

        int iTemp = tempCb.readInt();
        oBit = (iTemp & (byte) OFLAG_SET) == OFLAG_SET;
        iTemp = tempCb.readInt();
        label = (int) iTemp >> SHIFT_LABEL;

        // parse optional TLV
        optionalTlv = parseOptionalTlv(tempCb);
        return new PcepLabelObjectVer1(labelObjHeader, oBit, label, optionalTlv);
    }

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

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

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

        byte oFlag;

        oFlag = (byte) ((oBit) ? OFLAG_SET : OFLAG_RESET);
        cb.writeInt(oFlag);
        int temp = label;
        temp = (int) label << SHIFT_LABEL;
        cb.writeInt(temp);

        // Add optional TLV
        packOptionalTlv(cb);

        //Update object length now
        int length = cb.writerIndex() - objStartIndex;

        //will be helpful during print().
        labelObjHeader.setObjLen((short) length);
        cb.setShort(objLenIndex, (short) length);
        return cb.writerIndex();
    }

    /**
     * Returns list of optional tlvs.
     *
     * @param cb of type channel buffer
     * @return list of optional tlvs.
     * @throws PcepParseException when fails to parse list of optional tlvs
     */
    protected static LinkedList<PcepValueType> parseOptionalTlv(ChannelBuffer cb) throws PcepParseException {

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

        while (MINIMUM_COMMON_HEADER_LENGTH <= cb.readableBytes()) {

            PcepValueType tlv;
            short hType = cb.readShort();
            short hLength = cb.readShort();
            int iValue = 0;

            switch (hType) {

            case NexthopIPv4addressTlv.TYPE:
                iValue = cb.readInt();
                tlv = new NexthopIPv4addressTlv(iValue);
                break;
            case NexthopIPv6addressTlv.TYPE:
                byte[] ipv6Value = new byte[NexthopIPv6addressTlv.VALUE_LENGTH];
                cb.readBytes(ipv6Value, 0, NexthopIPv6addressTlv.VALUE_LENGTH);
                tlv = new NexthopIPv6addressTlv(ipv6Value);
                break;
            case NexthopUnnumberedIPv4IDTlv.TYPE:
                tlv = NexthopUnnumberedIPv4IDTlv.read(cb);
                break;
            default:
                throw new PcepParseException("Unsupported TLV type :" + hType);
            }

            // Check for the padding
            int pad = hLength % 4;
            if (0 < pad) {
                pad = 4 - pad;
                if (pad <= cb.readableBytes()) {
                    cb.skipBytes(pad);
                }
            }

            llOutOptionalTlv.add(tlv);
        }

        if (0 < cb.readableBytes()) {

            throw new PcepParseException("Optional Tlv parsing error. Extra bytes received.");
        }
        return llOutOptionalTlv;
    }

    /**
     * Returns the writer index.
     *
     * @param cb of channel buffer.
     * @return writer index
     */
    protected int packOptionalTlv(ChannelBuffer cb) {

        ListIterator<PcepValueType> listIterator = optionalTlv.listIterator();

        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();
    }

    /**
     * Builder class for PCEP label object.
     */
    public static class Builder implements PcepLabelObject.Builder {

        private boolean bIsHeaderSet = false;
        private boolean bIsOFlagSet = false;
        private boolean bIsLabelSet = false;

        private PcepObjectHeader labelObjHeader;
        private boolean oBit;
        private int label;

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

        private boolean bIsPFlagSet = false;
        private boolean bPFlag;

        private boolean bIsIFlagSet = false;
        private boolean bIFlag;

        @Override
        public PcepLabelObject build() throws PcepParseException {
            PcepObjectHeader labelObjHeader = this.bIsHeaderSet ? this.labelObjHeader : DEFAULT_LABEL_OBJECT_HEADER;
            boolean oBit = this.bIsOFlagSet ? this.oBit : DEFAULT_OFLAG;

            if (!this.bIsLabelSet) {
                throw new PcepParseException(" Label NOT Set while building PcepLabelObject.");
            }
            if (bIsPFlagSet) {
                labelObjHeader.setPFlag(bPFlag);
            }
            if (bIsIFlagSet) {
                labelObjHeader.setIFlag(bIFlag);
            }
            return new PcepLabelObjectVer1(labelObjHeader, oBit, this.label, this.optionalTlv);
        }

        @Override
        public PcepObjectHeader getLabelObjHeader() {
            return this.labelObjHeader;
        }

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

        @Override
        public boolean getOFlag() {
            return this.oBit;
        }

        @Override
        public Builder setOFlag(boolean value) {
            this.oBit = value;
            this.bIsOFlagSet = true;
            return this;
        }

        @Override
        public int getLabel() {
            return this.label;
        }

        @Override
        public Builder setLabel(int value) {
            this.label = value;
            this.bIsLabelSet = true;
            return this;
        }

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

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

        @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("oBit", oBit)
                .add("label", label)
                .add("optionalTlv", optionalTlv)
                .toString();
    }
}
