/*
 * 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.bgpio.protocol.ver4;

import java.util.LinkedList;
import java.util.ListIterator;

import org.jboss.netty.buffer.ChannelBuffer;
import org.onosproject.bgpio.exceptions.BgpParseException;
import org.onosproject.bgpio.protocol.BgpMessageReader;
import org.onosproject.bgpio.protocol.BgpMessageWriter;
import org.onosproject.bgpio.protocol.BgpOpenMsg;
import org.onosproject.bgpio.protocol.BgpType;
import org.onosproject.bgpio.protocol.BgpVersion;
import org.onosproject.bgpio.types.BgpErrorType;
import org.onosproject.bgpio.types.BgpHeader;
import org.onosproject.bgpio.types.BgpValueType;
import org.onosproject.bgpio.types.FourOctetAsNumCapabilityTlv;
import org.onosproject.bgpio.types.MultiProtocolExtnCapabilityTlv;
import org.onosproject.bgpio.util.Validation;
import org.onosproject.bgpio.util.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.MoreObjects;

/**
 * Provides BGP open message.
 */
public class BgpOpenMsgVer4 implements BgpOpenMsg {

    /*
       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
       +-+-+-+-+-+-+-+-+
       |    Version    |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |    My Autonomous System       |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |         Hold Time             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                  BGP Identifier                             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       | Opt Parm Len  |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |             Optional Parameters (variable)                  |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       OPEN Message Format
       REFERENCE : RFC 4271
    */

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

    public static final byte PACKET_VERSION = 4;
    public static final int OPEN_MSG_MINIMUM_LENGTH = 10;
    public static final int MSG_HEADER_LENGTH = 19;
    public static final int MARKER_LENGTH  = 16;
    public static final int DEFAULT_HOLD_TIME = 120;
    public static final short AS_TRANS = 23456;
    public static final int OPT_PARA_TYPE_CAPABILITY = 2;
    public static final BgpType MSG_TYPE = BgpType.OPEN;
    public static final short AFI = 16388;
    public static final byte SAFI = 71;
    public static final byte RES = 0;
    public static final int FOUR_OCTET_AS_NUM_CAPA_TYPE = 65;
    public static final byte[] MARKER = new byte[]{(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff};
    public static final BgpHeader DEFAULT_OPEN_HEADER = new BgpHeader(MARKER,
        (short) OPEN_MSG_MINIMUM_LENGTH, (byte) 0X01);
    private BgpHeader bgpMsgHeader;
    private byte version;
    private short asNumber;
    private short holdTime;
    private int bgpId;
    private boolean isLargeAsCapabilitySet;
    private LinkedList<BgpValueType> capabilityTlv;

    public static final BgpOpenMsgVer4.Reader READER = new Reader();

    /**
     * reset variables.
     */
    public BgpOpenMsgVer4() {
        this.bgpMsgHeader = null;
        this.version = 0;
        this.holdTime = 0;
        this.asNumber = 0;
        this.bgpId = 0;
        this.capabilityTlv = null;
    }

    /**
     * Constructor to initialize all variables of BGP Open message.
     *
     * @param bgpMsgHeader BGP Header in open message
     * @param version BGP version in open message
     * @param holdTime hold time in open message
     * @param asNumber AS number in open message
     * @param bgpId BGP identifier in open message
     * @param capabilityTlv capabilities in open message
     */
    public BgpOpenMsgVer4(BgpHeader bgpMsgHeader, byte version, short asNumber, short holdTime,
             int bgpId, LinkedList<BgpValueType> capabilityTlv) {
        this.bgpMsgHeader = bgpMsgHeader;
        this.version = version;
        this.asNumber = asNumber;
        this.holdTime = holdTime;
        this.bgpId = bgpId;
        this.capabilityTlv = capabilityTlv;
    }

    @Override
    public BgpHeader getHeader() {
        return this.bgpMsgHeader;
    }

    @Override
    public BgpVersion getVersion() {
        return BgpVersion.BGP_4;
    }

    @Override
    public BgpType getType() {
        return MSG_TYPE;
    }

    @Override
    public short getHoldTime() {
        return this.holdTime;
    }

    @Override
    public short getAsNumber() {
        return this.asNumber;
    }

    @Override
    public int getBgpId() {
        return this.bgpId;
    }

    @Override
    public LinkedList<BgpValueType> getCapabilityTlv() {
        return this.capabilityTlv;
    }

    /**
     * Reader class for reading BGP open message from channel buffer.
     */
    public static class Reader implements BgpMessageReader<BgpOpenMsg> {

        @Override
        public BgpOpenMsg readFrom(ChannelBuffer cb, BgpHeader bgpHeader) throws BgpParseException {

            byte version;
            short holdTime;
            short asNumber;
            int bgpId;
            byte optParaLen = 0;
            byte optParaType;
            byte capParaLen = 0;
            LinkedList<BgpValueType> capabilityTlv = new LinkedList<>();

            if (cb.readableBytes() < OPEN_MSG_MINIMUM_LENGTH) {
                log.error("[readFrom] Invalid length: Packet size is less than the minimum length ");
                Validation.validateLen(BgpErrorType.OPEN_MESSAGE_ERROR, BgpErrorType.BAD_MESSAGE_LENGTH,
                        cb.readableBytes());
            }

            // Read version
            version = cb.readByte();
            if (version != PACKET_VERSION) {
                log.error("[readFrom] Invalid version: " + version);
                throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR,
                        BgpErrorType.UNSUPPORTED_VERSION_NUMBER, null);
            }

            // Read AS number
            asNumber = cb.readShort();

            // Read Hold timer
            holdTime = cb.readShort();

            // Read BGP Identifier
            bgpId = cb.readInt();

            // Read optional parameter length
            optParaLen = cb.readByte();

            // Read Capabilities if optional parameter length is greater than 0
            if (optParaLen != 0) {
                // Read optional parameter type
                optParaType = cb.readByte();

                // Read optional parameter length
                capParaLen = cb.readByte();

                if (cb.readableBytes() < capParaLen) {
                    throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, (byte) 0, null);
                }

                ChannelBuffer capaCb = cb.readBytes(capParaLen);

                // Parse capabilities only if optional parameter type is 2
                if ((optParaType == OPT_PARA_TYPE_CAPABILITY) && (capParaLen != 0)) {
                    capabilityTlv = parseCapabilityTlv(capaCb);
                } else {
                    throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR,
                        BgpErrorType.UNSUPPORTED_OPTIONAL_PARAMETER, null);
                }
            }
            return new BgpOpenMsgVer4(bgpHeader, version, asNumber, holdTime, bgpId, capabilityTlv);
        }
    }

    /**
     * Parsing capabilities.
     *
     * @param cb of type channel buffer
     * @return capabilityTlv of open message
     * @throws BgpParseException while parsing capabilities
     */
    protected static LinkedList<BgpValueType> parseCapabilityTlv(ChannelBuffer cb) throws BgpParseException {

        LinkedList<BgpValueType> capabilityTlv = new LinkedList<>();

        while (cb.readableBytes() > 0) {
            BgpValueType tlv;
            short type = cb.readByte();
            short length = cb.readByte();

            switch (type) {
            case FourOctetAsNumCapabilityTlv.TYPE:
                log.debug("FourOctetAsNumCapabilityTlv");
                if (FourOctetAsNumCapabilityTlv.LENGTH != length) {
                    throw new BgpParseException("Invalid length received for FourOctetAsNumCapabilityTlv.");
                }
                if (length > cb.readableBytes()) {
                    throw new BgpParseException("Four octet as num tlv length"
                            + " is more than readableBytes.");
                }
                int as4Num = cb.readInt();
                tlv = new FourOctetAsNumCapabilityTlv(as4Num);
                break;
            case MultiProtocolExtnCapabilityTlv.TYPE:
                log.debug("MultiProtocolExtnCapabilityTlv");
                if (MultiProtocolExtnCapabilityTlv.LENGTH != length) {
                    throw new BgpParseException("Invalid length received for MultiProtocolExtnCapabilityTlv.");
                }
                if (length > cb.readableBytes()) {
                    throw new BgpParseException("BGP LS tlv length is more than readableBytes.");
                }
                short afi = cb.readShort();
                byte res = cb.readByte();
                byte safi = cb.readByte();
                tlv = new MultiProtocolExtnCapabilityTlv(afi, res, safi);
                break;
            default:
                log.debug("Warning: Unsupported TLV: " + type);
                cb.skipBytes(length);
                continue;
            }
            capabilityTlv.add(tlv);
        }
        return capabilityTlv;
    }

    /**
     * Builder class for BGP open message.
     */
    static class Builder implements BgpOpenMsg.Builder {

        private boolean isHeaderSet = false;
        private BgpHeader bgpMsgHeader;
        private boolean isHoldTimeSet = false;
        private short holdTime;
        private boolean isAsNumSet = false;
        private short asNumber;
        private boolean isBgpIdSet = false;
        private int bgpId;
        private boolean isIpV4UnicastCapabilityTlvSet = true;
        private boolean isLargeAsCapabilityTlvSet = false;
        private boolean isLsCapabilityTlvSet = false;
        private boolean isFlowSpecCapabilityTlvSet = false;
        private boolean isVpnFlowSpecCapabilityTlvSet = false;

        LinkedList<BgpValueType> capabilityTlv = new LinkedList<>();

        @Override
        public BgpOpenMsg build() throws BgpParseException {
            BgpHeader bgpMsgHeader = this.isHeaderSet ? this.bgpMsgHeader : DEFAULT_OPEN_HEADER;
            short holdTime = this.isHoldTimeSet ? this.holdTime : DEFAULT_HOLD_TIME;

            if (!this.isAsNumSet) {
                throw new BgpParseException("BGP AS number is not set (mandatory)");
            }

            if (!this.isBgpIdSet) {
                throw new BgpParseException("BGPID  is not set (mandatory)");
            }

            if (this.isIpV4UnicastCapabilityTlvSet) {
                BgpValueType tlv;
                tlv = new MultiProtocolExtnCapabilityTlv((short) Constants.AFI_IPV4_UNICAST, RES,
                                                         (byte) Constants.SAFI_IPV4_UNICAST);
                this.capabilityTlv.add(tlv);
            }

            if (this.isLargeAsCapabilityTlvSet) {
                BgpValueType tlv;
                int value = this.asNumber;
                tlv = new FourOctetAsNumCapabilityTlv(value);
                this.capabilityTlv.add(tlv);
            }

            if (this.isLsCapabilityTlvSet) {
                BgpValueType tlv;
                tlv = new MultiProtocolExtnCapabilityTlv(AFI, RES, SAFI);
                this.capabilityTlv.add(tlv);
            }

            if (this.isFlowSpecCapabilityTlvSet) {
                BgpValueType tlv;
                tlv = new MultiProtocolExtnCapabilityTlv(Constants.AFI_FLOWSPEC_VALUE,
                                                         RES, Constants.SAFI_FLOWSPEC_VALUE);
                this.capabilityTlv.add(tlv);
            }

            if (this.isVpnFlowSpecCapabilityTlvSet) {
                BgpValueType tlv;
                tlv = new MultiProtocolExtnCapabilityTlv(Constants.AFI_FLOWSPEC_VALUE,
                                                         RES, Constants.VPN_SAFI_FLOWSPEC_VALUE);
                this.capabilityTlv.add(tlv);
            }

            return new BgpOpenMsgVer4(bgpMsgHeader, PACKET_VERSION, this.asNumber, holdTime, this.bgpId,
                       this.capabilityTlv);
        }

        @Override
        public Builder setHeader(BgpHeader bgpMsgHeader) {
            this.bgpMsgHeader = bgpMsgHeader;
            return this;
        }

        @Override
        public Builder setHoldTime(short holdTime) {
            this.holdTime = holdTime;
            this.isHoldTimeSet = true;
            return this;
        }

        @Override
        public Builder setAsNumber(short asNumber) {
            this.asNumber = asNumber;
            this.isAsNumSet = true;
            return this;
        }

        @Override
        public Builder setBgpId(int bgpId) {
            this.bgpId = bgpId;
            this.isBgpIdSet = true;
            return this;
        }

        @Override
        public Builder setCapabilityTlv(LinkedList<BgpValueType> capabilityTlv) {
            this.capabilityTlv = capabilityTlv;
            return this;
        }

        @Override
        public Builder setLargeAsCapabilityTlv(boolean isLargeAsCapabilitySet) {
            this.isLargeAsCapabilityTlvSet = isLargeAsCapabilitySet;
            return this;
        }

        @Override
        public Builder setLsCapabilityTlv(boolean isLsCapabilitySet) {
            this.isLsCapabilityTlvSet = isLsCapabilitySet;
            return this;
        }

        @Override
        public Builder setFlowSpecCapabilityTlv(boolean isFlowSpecCapabilitySet) {
            this.isFlowSpecCapabilityTlvSet = isFlowSpecCapabilitySet;
            return this;
        }

        @Override
        public Builder setVpnFlowSpecCapabilityTlv(boolean isVpnFlowSpecCapabilitySet) {
            this.isVpnFlowSpecCapabilityTlvSet = isVpnFlowSpecCapabilitySet;
            return this;
        }
    }

    @Override
    public void writeTo(ChannelBuffer cb) {
        try {
            WRITER.write(cb, this);
        } catch (BgpParseException e) {
            log.debug("[writeTo] Error: " + e.toString());
        }
    }

    public static final Writer WRITER = new Writer();

    /**
     * Writer class for writing BGP open message to channel buffer.
     */
    public static class Writer implements BgpMessageWriter<BgpOpenMsgVer4> {

        @Override
        public void write(ChannelBuffer cb, BgpOpenMsgVer4 message) throws BgpParseException {

            int optParaLen = 0;
            int as4num = 0;

            int startIndex = cb.writerIndex();

            // write common header and get msg length index
            int msgLenIndex = message.bgpMsgHeader.write(cb);

            if (msgLenIndex <= 0) {
                throw new BgpParseException("Unable to write message header.");
            }

            // write version in 1-octet
            cb.writeByte(message.version);

            // get as4num if LS Capability is set
            if (message.isLargeAsCapabilitySet) {
                LinkedList<BgpValueType> capabilityTlv = message
                        .getCapabilityTlv();
                ListIterator<BgpValueType> listIterator = capabilityTlv
                        .listIterator();

                while (listIterator.hasNext()) {
                    BgpValueType tlv = listIterator.next();
                    if (tlv.getType() == FOUR_OCTET_AS_NUM_CAPA_TYPE) {
                        as4num = ((FourOctetAsNumCapabilityTlv) tlv).getInt();
                        break;
                    }
                }
            }

            if ((message.isLargeAsCapabilitySet) && (as4num > 65535)) {
                // write As number as AS_TRANS
                cb.writeShort(AS_TRANS);
            } else {
                // write AS number in next 2-octet
                cb.writeShort(message.asNumber);
            }

            // write HoldTime in next 2-octet
            cb.writeShort(message.holdTime);

            // write BGP Identifier in next 4-octet
            cb.writeInt(message.bgpId);

            // store the index of Optional parameter length
            int optParaLenIndex = cb.writerIndex();

            // set optional parameter length as 0
            cb.writeByte(0);

            // Pack capability TLV
            optParaLen = message.packCapabilityTlv(cb, message);

            if (optParaLen != 0) {
                // Update optional parameter length
                cb.setByte(optParaLenIndex, (byte) (optParaLen + 2)); //+2 for optional parameter type.
            }

            // write OPEN Object Length
            int length = cb.writerIndex() - startIndex;
            cb.setShort(msgLenIndex, (short) length);
            message.bgpMsgHeader.setLength((short) length);
        }
    }

    /**
     * returns length of capability tlvs.
     *
     * @param cb of type channel buffer
     * @param message of type BGPOpenMsgVer4
     * @return capParaLen of open message
     */
    protected int packCapabilityTlv(ChannelBuffer cb, BgpOpenMsgVer4 message) {
        int startIndex = cb.writerIndex();
        int capParaLen = 0;
        int capParaLenIndex = 0;

        LinkedList<BgpValueType> capabilityTlv = message.capabilityTlv;
        ListIterator<BgpValueType> listIterator = capabilityTlv.listIterator();

        if (listIterator.hasNext()) {
            // Set optional parameter type as 2
            cb.writeByte(OPT_PARA_TYPE_CAPABILITY);

            // Store the index of capability parameter length and update length at the end
            capParaLenIndex = cb.writerIndex();

            // Set capability parameter length as 0
            cb.writeByte(0);

            // Update the startIndex to know the length of capability tlv
            startIndex = cb.writerIndex();
        }

        while (listIterator.hasNext()) {
            BgpValueType tlv = listIterator.next();
            if (tlv == null) {
                log.debug("Warning: tlv is null from CapabilityTlv list");
                continue;
            }
            tlv.write(cb);
        }

        capParaLen = cb.writerIndex() - startIndex;

        if (capParaLen != 0) {
            // Update capability parameter length
            cb.setByte(capParaLenIndex, (byte) capParaLen);
        }
        return capParaLen;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(getClass())
            .add("bgpMsgHeader", bgpMsgHeader)
            .add("version", version)
            .add("holdTime", holdTime)
            .add("asNumber", asNumber)
            .add("bgpId", bgpId)
            .add("capabilityTlv", capabilityTlv)
            .toString();
    }
}
