/*
 * 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.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 isLargeAsCapabilityTlvSet = false;
        private boolean isLsCapabilityTlvSet = 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.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);
            }

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