/*
 * 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.PcepTEObject;
import org.onosproject.pcepio.types.LocalTENodeDescriptorsTLV;
import org.onosproject.pcepio.types.PcepObjectHeader;
import org.onosproject.pcepio.types.PcepValueType;
import org.onosproject.pcepio.types.RemoteTENodeDescriptorsTLV;
import org.onosproject.pcepio.types.RoutingUniverseTLV;
import org.onosproject.pcepio.types.TELinkAttributesTlv;
import org.onosproject.pcepio.types.TELinkDescriptorsTLV;
import org.onosproject.pcepio.types.TENodeAttributesTlv;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.MoreObjects;

/**
 * Provides PCEP TE Object.
 */
public class PcepTEObjectVer1 implements PcepTEObject {
    /*
     *
    reference: PCEP Extension for Transporting TE Data draft-dhodylee-pce-pcep-te-data-extn-02.
    TE Object-Class is [TBD6].

    Two Object-Type values are defined for the TE object:

    o  TE Node: TE Object-Type is 1.

    o  TE Link: TE Object-Type is 2.

    The format of the TE object body is as follows:

       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
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |  Protocol-ID  |          Flag                             |R|S|
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                          TE-ID                                |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      //                         TLVs                                //
      |                                                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     */

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

    public static final byte TE_OBJ_TYPE_NODE_VALUE = 1;
    public static final byte TE_OBJ_TYPE_LINK_VALUE = 2;

    public static final byte TE_OBJ_CLASS = 101; //TBD6 in RFC.
    public static final byte TE_OBJECT_VERSION = 1;

    // TE_OBJ_MINIMUM_LENGTH = TEObjectHeaderLen(4)+ TEObjectLen(8)
    public static final short TE_OBJ_MINIMUM_LENGTH = 12;

    // Signaled ,all default values to be checked.
    public static final byte DEFAULT_PROTOCOL_ID = 1; //IS-IS Level 1
    public static final boolean DEFAULT_R_FLAG = false;
    public static final boolean DEFAULT_S_FLAG = false;
    public static final int DEFAULT_TE_ID = 0;

    public static final int OBJECT_HEADER_LENGTH = 4;
    public static final int RIGHT_SHIFT_ONE = 1;
    public static final int RIGHT_FIRST_FLAG = 0x1;
    public static final int FLAG_SET_R_FLAG = 0x2;
    public static final int FLAG_SET_S_FLAG = 0x1;
    public static final int MINIMUM_COMMON_HEADER_LENGTH = 4;
    public static final int MINIMUM_TLV_HEADER_LENGTH = 4;

    public static final PcepObjectHeader DEFAULT_TE_OBJECT_HEADER = new PcepObjectHeader(TE_OBJ_CLASS,
            TE_OBJ_TYPE_NODE_VALUE, PcepObjectHeader.REQ_OBJ_OPTIONAL_PROCESS, PcepObjectHeader.RSP_OBJ_PROCESSED,
            TE_OBJ_MINIMUM_LENGTH);

    private PcepObjectHeader teObjHeader;
    private byte yProtocolId;
    // 2-flags
    private boolean bRFlag;
    private boolean bSFlag;
    private int iTEId;
    // Optional TLV
    private LinkedList<PcepValueType> llOptionalTlv;

    /**
     * Constructor to initialize variables.
     *
     * @param teObjHeader TE Object header
     * @param yProtocolId Protocol-ID
     * @param bRFlag R-flag
     * @param bSFlag S-flag
     * @param iTEId TE-ID
     * @param llOptionalTlv linked list of Optional TLV
     */
    public PcepTEObjectVer1(PcepObjectHeader teObjHeader, byte yProtocolId, boolean bRFlag, boolean bSFlag, int iTEId,
            LinkedList<PcepValueType> llOptionalTlv) {

        this.teObjHeader = teObjHeader;
        this.yProtocolId = yProtocolId;
        this.bRFlag = bRFlag;
        this.bSFlag = bSFlag;
        this.iTEId = iTEId;
        this.llOptionalTlv = llOptionalTlv;
    }

    @Override
    public PcepObjectHeader getTEObjHeader() {
        return this.teObjHeader;
    }

    @Override
    public void setTEObjHeader(PcepObjectHeader obj) {
        this.teObjHeader = obj;
    }

    @Override
    public byte getProtocolId() {
        return this.yProtocolId;
    }

    @Override
    public void setProtocolId(byte yProtId) {
        this.yProtocolId = yProtId;
    }

    @Override
    public boolean getRFlag() {
        return this.bRFlag;
    }

    @Override
    public void setRFlag(boolean bRFlag) {
        this.bRFlag = bRFlag;
    }

    @Override
    public boolean getSFlag() {
        return this.bSFlag;
    }

    @Override
    public void setSFlag(boolean bSFlag) {
        this.bSFlag = bSFlag;
    }

    @Override
    public int getTEId() {
        return this.iTEId;
    }

    @Override
    public void setTEId(int iTEId) {
        this.iTEId = iTEId;
    }

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

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

    /**
     * Reads from the channel buffer and returns Object of PcepTEObject.
     *
     * @param cb of type channel buffer
     * @return Object of PcepTEObject
     * @throws PcepParseException if mandatory fields are missing
     */
    public static PcepTEObject read(ChannelBuffer cb) throws PcepParseException {
        log.debug("read");

        PcepObjectHeader teObjHeader;
        byte yProtocolId;
        // 2-flags
        boolean bRFlag;
        boolean bSFlag;
        int iTEId;
        LinkedList<PcepValueType> llOptionalTlv;

        teObjHeader = PcepObjectHeader.read(cb);

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

        yProtocolId = tempCb.readByte();
        //ignore first two bytes of Flags
        tempCb.readShort();

        Integer iTemp = (int) tempCb.readByte(); //read 3rd byte Flag
        bSFlag = ((iTemp & FLAG_SET_S_FLAG) == FLAG_SET_S_FLAG) ? true : false;
        bRFlag = ((iTemp & FLAG_SET_R_FLAG) == FLAG_SET_R_FLAG) ? true : false;

        iTEId = tempCb.readInt();

        // parse optional TLV
        llOptionalTlv = parseOptionalTlv(tempCb);

        return new PcepTEObjectVer1(teObjHeader, yProtocolId, bRFlag, bSFlag, iTEId, llOptionalTlv);
    }

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

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

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

        //write Protocol ID
        cb.writeByte(this.yProtocolId);

        //write Flag
        cb.writeShort(0);

        byte bTemp = 0;
        if (bSFlag) {
            bTemp = FLAG_SET_S_FLAG;
        }

        if (bRFlag) {
            bTemp = (byte) (bTemp | FLAG_SET_R_FLAG);
        }
        cb.writeByte(bTemp);

        //write TEId
        cb.writeInt(iTEId);

        // Add optional TLV
        packOptionalTlv(cb);

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

        //will be helpful during print().
        teObjHeader.setObjLen((short) length);

        cb.setShort(objLenIndex, (short) length);

        return cb.writerIndex();
    }

    /**
     * Returns Linked list of PCEP Value Type.
     *
     * @param cb of channel buffer
     * @return Linked list of PCEP Value Type
     * @throws PcepParseException if mandatory fields are missing
     */
    protected static LinkedList<PcepValueType> parseOptionalTlv(ChannelBuffer cb) throws PcepParseException {

        LinkedList<PcepValueType> llOutOptionalTlv;

        llOutOptionalTlv = new LinkedList<PcepValueType>();

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

            PcepValueType tlv;
            short hType = cb.readShort();
            short hLength = cb.readShort();
            long lValue = 0;

            switch (hType) {

            case RoutingUniverseTLV.TYPE:
                lValue = cb.readLong();
                tlv = new RoutingUniverseTLV(lValue);
                break;
            case LocalTENodeDescriptorsTLV.TYPE:
                tlv = LocalTENodeDescriptorsTLV.read(cb, hLength);
                break;
            case RemoteTENodeDescriptorsTLV.TYPE:
                tlv = RemoteTENodeDescriptorsTLV.read(cb, hLength);
                break;
            case TELinkDescriptorsTLV.TYPE:
                tlv = TELinkDescriptorsTLV.read(cb, hLength);
                break;
            case TENodeAttributesTlv.TYPE:
                tlv = TENodeAttributesTlv.read(cb, hLength);
                break;
            case TELinkAttributesTlv.TYPE:
                tlv = TELinkAttributesTlv.read(cb, hLength);
                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 type channel buffer
     * @return the writer index.
     */
    protected int packOptionalTlv(ChannelBuffer cb) {

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

        while (listIterator.hasNext()) {
            PcepValueType tlv = listIterator.next();

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

            // need to take care of padding
            int pad = tlv.getLength() % 4;

            if (0 != pad) {
                pad = 4 - pad;
                for (int i = 0; i < pad; ++i) {
                    cb.writeByte((byte) 0);
                }
            }
        }
        return cb.writerIndex();
    }

    /**
     * Builder class for PCEP te object.
     */
    public static class Builder implements PcepTEObject.Builder {
        private boolean bIsHeaderSet = false;
        private boolean bIsProtocolIdSet = false;
        private boolean bIsRFlagSet = false;
        private boolean bIsSFlagSet = false;
        private boolean bIsTEIdSet = false;

        private PcepObjectHeader teObjHeader;
        private byte yProtocolId;
        private boolean bRFlag;
        private boolean bSFlag;
        private int iTEId;
        private LinkedList<PcepValueType> llOptionalTlv = new LinkedList<PcepValueType>();

        private boolean bIsPFlagSet = false;
        private boolean bPFlag;

        private boolean bIsIFlagSet = false;
        private boolean bIFlag;

        @Override
        public PcepTEObject build() {
            PcepObjectHeader teObjHeader = this.bIsHeaderSet ? this.teObjHeader : DEFAULT_TE_OBJECT_HEADER;

            byte yProtocolId = this.bIsProtocolIdSet ? this.yProtocolId : DEFAULT_PROTOCOL_ID;
            boolean bRFlag = this.bIsRFlagSet ? this.bRFlag : DEFAULT_R_FLAG;
            boolean bSFlag = this.bIsSFlagSet ? this.bSFlag : DEFAULT_S_FLAG;
            int iTEId = this.bIsTEIdSet ? this.iTEId : DEFAULT_TE_ID;

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

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

            return new PcepTEObjectVer1(teObjHeader, yProtocolId, bRFlag, bSFlag, iTEId, llOptionalTlv);

        }

        @Override
        public PcepObjectHeader getTEObjHeader() {
            return this.teObjHeader;
        }

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

        @Override
        public byte getProtocolId() {
            return this.yProtocolId;
        }

        @Override
        public Builder setProtocolId(byte yProtId) {
            this.yProtocolId = yProtId;
            this.bIsProtocolIdSet = true;
            return this;
        }

        @Override
        public boolean getRFlag() {
            return this.bRFlag;
        }

        @Override
        public Builder setRFlag(boolean bRFlag) {
            this.bRFlag = bRFlag;
            this.bIsRFlagSet = true;
            return this;
        }

        @Override
        public boolean getSFlag() {
            return this.bSFlag;
        }

        @Override
        public Builder setSFlag(boolean bSFlag) {
            this.bSFlag = bSFlag;
            this.bIsSFlagSet = true;
            return this;
        }

        @Override
        public int getTEId() {
            return this.iTEId;
        }

        @Override
        public Builder setTEId(int iTEId) {
            this.iTEId = iTEId;
            this.bIsTEIdSet = true;
            return this;
        }

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

        @Override
        public Builder setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) {
            this.llOptionalTlv = llOptionalTlv;
            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("ObjectHeader", teObjHeader).add("ProtocolId", yProtocolId)
                .add("RFlag", (bRFlag) ? 1 : 0).add("SFlag", (bSFlag) ? 1 : 0).add("TeId", iTEId)
                .add("OptionalTlv", llOptionalTlv).toString();
    }
}
