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

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:
                RemoteTENodeDescriptorsTLV.hLength = hLength;
                tlv = RemoteTENodeDescriptorsTLV.read(cb);
                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 (null == tlv) {
                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();
    }

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