/*
 * Copyright 2016-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.List;
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.PcepLSObject;
import org.onosproject.pcepio.types.LocalNodeDescriptorsTlv;
import org.onosproject.pcepio.types.PcepObjectHeader;
import org.onosproject.pcepio.types.PcepValueType;
import org.onosproject.pcepio.types.RemoteNodeDescriptorsTlv;
import org.onosproject.pcepio.types.RoutingUniverseTlv;
import org.onosproject.pcepio.types.LinkAttributesTlv;
import org.onosproject.pcepio.types.LinkDescriptorsTlv;
import org.onosproject.pcepio.types.NodeAttributesTlv;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.MoreObjects;

/**
 * Provides PCEP LS (link-state) object.
 */
public class PcepLSObjectVer1 implements PcepLSObject {
    /*
     *
    reference: draft-dhodylee-pce-pcep-ls-01, section 9.2.

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

    o  LS Node: LS Object-Type is 1.

    o  LS Link: LS Object-Type is 2.

    o  LS IPv4 Topology Prefix: LS Object-Type is 3.

    o  LS IPv6 Topology Prefix: LS Object-Type is 4.

    The format of the LS 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|
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                          LS-ID                                |
      |                                                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      //                         TLVs                                //
      |                                                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     */

    private static final Logger log = LoggerFactory.getLogger(PcepLSObjectVer1.class);

    public static final byte LS_OBJ_TYPE_NODE_VALUE = 1;
    public static final byte LS_OBJ_TYPE_LINK_VALUE = 2;

    public static final byte LS_OBJ_CLASS = (byte) 224;
    public static final byte LS_OBJECT_VERSION = 1;

    // LS_OBJ_MINIMUM_LENGTH = LSObjectHeaderLen(4) + LSObjectLen(8)
    public static final short LS_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_LS_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_LS_OBJECT_HEADER = new PcepObjectHeader(LS_OBJ_CLASS,
            LS_OBJ_TYPE_NODE_VALUE, PcepObjectHeader.REQ_OBJ_OPTIONAL_PROCESS, PcepObjectHeader.RSP_OBJ_PROCESSED,
            LS_OBJ_MINIMUM_LENGTH);

    private PcepObjectHeader lsObjHeader;
    private byte protocolId;
    // 2-flags
    private boolean removeFlag;
    private boolean syncFlag;
    private long lsId; //link-state identifier
    // Optional TLV
    private List<PcepValueType> optionalTlvList;

    /**
     * Constructor to initialize variables.
     *
     * @param lsObjHeader LS Object header
     * @param protocolId Protocol-ID
     * @param removeFlag R-flag
     * @param syncFlag S-flag
     * @param lsId LS-ID
     * @param optionalTlvList linked list of Optional TLV
     */
    public PcepLSObjectVer1(PcepObjectHeader lsObjHeader, byte protocolId, boolean removeFlag,
            boolean syncFlag, long lsId, List<PcepValueType> optionalTlvList) {

        this.lsObjHeader = lsObjHeader;
        this.protocolId = protocolId;
        this.removeFlag = removeFlag;
        this.syncFlag = syncFlag;
        this.lsId = lsId;
        this.optionalTlvList = optionalTlvList;
    }

    @Override
    public PcepObjectHeader getLSObjHeader() {
        return this.lsObjHeader;
    }

    @Override
    public void setLSObjHeader(PcepObjectHeader obj) {
        this.lsObjHeader = obj;
    }

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

    @Override
    public void setProtocolId(byte protId) {
        this.protocolId = protId;
    }

    @Override
    public boolean getRemoveFlag() {
        return this.removeFlag;
    }

    @Override
    public void setRemoveFlag(boolean removeFlag) {
        this.removeFlag = removeFlag;
    }

    @Override
    public boolean getSyncFlag() {
        return this.syncFlag;
    }

    @Override
    public void setSyncFlag(boolean syncFlag) {
        this.syncFlag = syncFlag;
    }

    @Override
    public long getLSId() {
        return this.lsId;
    }

    @Override
    public void setLSId(long lsId) {
        this.lsId = lsId;
    }

    @Override
    public List<PcepValueType> getOptionalTlv() {
        return this.optionalTlvList;
    }

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

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

        PcepObjectHeader lsObjHeader;
        byte protocolId;
        // 2-flags
        boolean removeFlag;
        boolean syncFlag;
        long lsId;
        List<PcepValueType> optionalTlvList;

        lsObjHeader = PcepObjectHeader.read(cb);

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

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

        Integer iTemp = (int) tempCb.readByte(); //read 3rd byte Flag
        syncFlag = (iTemp & FLAG_SET_S_FLAG) == FLAG_SET_S_FLAG;
        removeFlag = (iTemp & FLAG_SET_R_FLAG) == FLAG_SET_R_FLAG;

        lsId = tempCb.readLong();

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

        return new PcepLSObjectVer1(lsObjHeader, protocolId, removeFlag, syncFlag, lsId, optionalTlvList);
    }

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

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

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

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

        //write Flag
        cb.writeShort(0);

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

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

        //write LSId
        cb.writeLong(lsId);

        // Add optional TLV
        packOptionalTlv(cb);

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

        //will be helpful during print().
        lsObjHeader.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 List<PcepValueType> parseOptionalTlv(ChannelBuffer cb) throws PcepParseException {

        List<PcepValueType> llOutOptionalTlv;

        llOutOptionalTlv = new LinkedList<>();

        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 LocalNodeDescriptorsTlv.TYPE:
                tlv = LocalNodeDescriptorsTlv.read(cb, hLength);
                break;
            case RemoteNodeDescriptorsTlv.TYPE:
                tlv = RemoteNodeDescriptorsTlv.read(cb, hLength);
                break;
            case LinkDescriptorsTlv.TYPE:
                tlv = LinkDescriptorsTlv.read(cb, hLength);
                break;
            case NodeAttributesTlv.TYPE:
                tlv = NodeAttributesTlv.read(cb, hLength);
                break;
            case LinkAttributesTlv.TYPE:
                tlv = LinkAttributesTlv.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 = optionalTlvList.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 LS (link-state) object.
     */
    public static class Builder implements PcepLSObject.Builder {
        private boolean isHeaderSet = false;
        private boolean isProtocolIdSet = false;
        private boolean isRemoveFlagSet = false;
        private boolean isSyncFlagSet = false;
        private boolean isLSIdSet = false;

        private PcepObjectHeader lsObjHeader;
        private byte protocolId;
        private boolean removeFlag;
        private boolean syncFlag;
        private long lsId;
        private List<PcepValueType> optionalTlvList = new LinkedList<>();

        private boolean isProcRuleFlagSet = false;
        private boolean procRuleFlag; //Processing rule flag

        private boolean isIgnoreFlagSet = false;
        private boolean ignoreFlag;

        @Override
        public PcepLSObject build() {
            PcepObjectHeader lsObjHeader = this.isHeaderSet ? this.lsObjHeader : DEFAULT_LS_OBJECT_HEADER;

            byte protocolId = this.isProtocolIdSet ? this.protocolId : DEFAULT_PROTOCOL_ID;
            boolean removeFlag = this.isRemoveFlagSet ? this.removeFlag : DEFAULT_R_FLAG;
            boolean syncFlag = this.isSyncFlagSet ? this.syncFlag : DEFAULT_S_FLAG;
            long lsId = this.isLSIdSet ? this.lsId : DEFAULT_LS_ID;

            if (isProcRuleFlagSet) {
                lsObjHeader.setPFlag(procRuleFlag);
            }

            if (isIgnoreFlagSet) {
                lsObjHeader.setIFlag(ignoreFlag);
            }

            return new PcepLSObjectVer1(lsObjHeader, protocolId, removeFlag, syncFlag, lsId, optionalTlvList);

        }

        @Override
        public PcepObjectHeader getLSObjHeader() {
            return this.lsObjHeader;
        }

        @Override
        public Builder setLSObjHeader(PcepObjectHeader obj) {
            this.lsObjHeader = obj;
            this.isHeaderSet = true;
            return this;
        }

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

        @Override
        public Builder setProtocolId(byte protId) {
            this.protocolId = protId;
            this.isProtocolIdSet = true;
            return this;
        }

        @Override
        public boolean getRemoveFlag() {
            return this.removeFlag;
        }

        @Override
        public Builder setRemoveFlag(boolean removeFlag) {
            this.removeFlag = removeFlag;
            this.isRemoveFlagSet = true;
            return this;
        }

        @Override
        public boolean getSyncFlag() {
            return this.syncFlag;
        }

        @Override
        public Builder setSyncFlag(boolean syncFlag) {
            this.syncFlag = syncFlag;
            this.isSyncFlagSet = true;
            return this;
        }

        @Override
        public long getLSId() {
            return this.lsId;
        }

        @Override
        public Builder setLSId(long lsId) {
            this.lsId = lsId;
            this.isLSIdSet = true;
            return this;
        }

        @Override
        public List<PcepValueType> getOptionalTlv() {
            return this.optionalTlvList;
        }

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

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

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

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(getClass()).omitNullValues()
                .add("ObjectHeader", lsObjHeader)
                .add("ProtocolId", protocolId)
                .add("RFlag", (removeFlag) ? 1 : 0)
                .add("SFlag", (syncFlag) ? 1 : 0)
                .add("LsId", lsId)
                .add("OptionalTlv", optionalTlvList).toString();
    }
}
