/*
 * Copyright 2015-present 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.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.jboss.netty.buffer.ChannelBuffer;
import org.onlab.packet.IpPrefix;
import org.onosproject.bgpio.exceptions.BgpParseException;
import org.onosproject.bgpio.protocol.BgpMessageReader;
import org.onosproject.bgpio.protocol.BgpMessageWriter;
import org.onosproject.bgpio.protocol.BgpType;
import org.onosproject.bgpio.protocol.BgpUpdateMsg;
import org.onosproject.bgpio.protocol.BgpVersion;
import org.onosproject.bgpio.types.BgpErrorType;
import org.onosproject.bgpio.types.BgpHeader;
import org.onosproject.bgpio.types.MpReachNlri;
import org.onosproject.bgpio.types.MpUnReachNlri;
import org.onosproject.bgpio.util.Constants;
import org.onosproject.bgpio.util.Validation;

import org.onosproject.bgpio.types.BgpValueType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.MoreObjects;

/**
 * BGP Update Message: UPDATE messages are used to transfer routing information
 * between BGP peers. The information in the UPDATE message is used by core to
 * construct a graph
 */
public class BgpUpdateMsgVer4 implements BgpUpdateMsg {

    /*      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
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                                                               |
    +                                                               +
    |                                                               |
    +                                                               +
    |                           Marker                              |
    +                                                               +
    |                                                               |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |          Length               |      Type     |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |   Withdrawn Routes Length (2 octets)                |
    +-----------------------------------------------------+
    |   Withdrawn Routes (variable)                       |
    +-----------------------------------------------------+
    |   Total Path Attribute Length (2 octets)            |
    +-----------------------------------------------------+
    |   Path Attributes (variable)                        |
    +-----------------------------------------------------+
    |   Network Layer Reachability Information (variable) |
    +-----------------------------------------------------+
    REFERENCE : RFC 4271
    */

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

    public static final byte PACKET_VERSION = 4;
    //Withdrawn Routes Length(2) + Total Path Attribute Length(2)
    public static final int PACKET_MINIMUM_LENGTH = 4;
    public static final int MARKER_LENGTH = 16;
    public static final int BYTE_IN_BITS = 8;
    public static final int MIN_LEN_AFTER_WITHDRW_ROUTES = 2;
    public static final int MINIMUM_COMMON_HEADER_LENGTH = 19;
    public static final BgpType MSG_TYPE = BgpType.UPDATE;
    public static 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_UPDATE_HEADER = new BgpHeader(marker,
                                                                        (short) PACKET_MINIMUM_LENGTH, (byte) 0X02);
    public static final BgpUpdateMsgVer4.Reader READER = new Reader();

    private List<IpPrefix> withdrawnRoutes;
    private BgpPathAttributes bgpPathAttributes;
    private BgpHeader bgpHeader;
    private List<IpPrefix> nlri;

    /**
     * Constructor to initialize parameters for BGP Update message.
     *
     * @param bgpHeader in Update message
     * @param withdrawnRoutes withdrawn routes
     * @param bgpPathAttributes BGP Path attributes
     * @param nlri Network Layer Reachability Information
     */
    public BgpUpdateMsgVer4(BgpHeader bgpHeader, List<IpPrefix> withdrawnRoutes,
                     BgpPathAttributes bgpPathAttributes, List<IpPrefix> nlri) {
        this.bgpHeader = bgpHeader;
        this.withdrawnRoutes = withdrawnRoutes;
        this.bgpPathAttributes = bgpPathAttributes;
        this.nlri = nlri;
    }

    /**
     * Reader reads BGP Update Message from the channel buffer.
     */
    static class Reader implements BgpMessageReader<BgpUpdateMsg> {

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

            if (cb.readableBytes() != (bgpHeader.getLength() - MINIMUM_COMMON_HEADER_LENGTH)) {
                Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
                        BgpErrorType.BAD_MESSAGE_LENGTH, bgpHeader.getLength());
            }

            LinkedList<IpPrefix> withDrwRoutes = new LinkedList<>();
            LinkedList<IpPrefix> nlri = new LinkedList<>();
            BgpPathAttributes bgpPathAttributes = new BgpPathAttributes();

            Short withDrwLen = cb.readShort();

            if (cb.readableBytes() < withDrwLen) {
                Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
                        BgpErrorType.MALFORMED_ATTRIBUTE_LIST,
                        cb.readableBytes());
            }
            log.debug("Reading withdrawn routes length");
            ChannelBuffer tempCb = cb.readBytes(withDrwLen);
            if (withDrwLen != 0) {
                // Parsing WithdrawnRoutes
                withDrwRoutes = parseWithdrawnRoutes(tempCb);
                log.debug("Withdrawn routes parsed");
            }
            if (cb.readableBytes() < MIN_LEN_AFTER_WITHDRW_ROUTES) {
                log.debug("Bgp path attribute len field not present");
                throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR,
                        BgpErrorType.MALFORMED_ATTRIBUTE_LIST, null);
            }

            // Reading Total Path Attribute Length
            short totPathAttrLen = cb.readShort();
            int len = withDrwLen + totPathAttrLen + PACKET_MINIMUM_LENGTH;
            if (len > bgpHeader.getLength()) {
                throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR,
                        BgpErrorType.MALFORMED_ATTRIBUTE_LIST, null);
            }
            log.debug("Total path attribute length read");
            if (totPathAttrLen != 0) {
                // Parsing BGPPathAttributes
                if (cb.readableBytes() < totPathAttrLen) {
                    Validation
                            .validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
                                         BgpErrorType.MALFORMED_ATTRIBUTE_LIST,
                                         cb.readableBytes());
                }
                tempCb = cb.readBytes(totPathAttrLen);
                bgpPathAttributes = BgpPathAttributes.read(tempCb);
            }
            if (cb.readableBytes() > 0) {
                // Parsing NLRI
                nlri = parseNlri(cb);
            }
            return new BgpUpdateMsgVer4(bgpHeader, withDrwRoutes,
                    bgpPathAttributes, nlri);
        }
    }

    /**
     * Builder class for BGP update message.
     */
    static class Builder implements BgpUpdateMsg.Builder {
        BgpHeader bgpMsgHeader = null;
        BgpPathAttributes bgpPathAttributes;
        List<IpPrefix> withdrawnRoutes;
        List<IpPrefix> nlri;

        @Override
        public BgpUpdateMsg build() {
            BgpHeader bgpMsgHeader = DEFAULT_UPDATE_HEADER;

            return new BgpUpdateMsgVer4(bgpMsgHeader, withdrawnRoutes, bgpPathAttributes, nlri);
        }

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

        @Override
        public Builder setBgpPathAttributes(List<BgpValueType> attributes) {
            this.bgpPathAttributes = new BgpPathAttributes(attributes);
            return this;
        }

    }

    public static final Writer WRITER = new Writer();

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

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

            int startIndex = cb.writerIndex();
            short afi = 0;
            byte safi = 0;

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

            if (msgLenIndex <= 0) {
                throw new BgpParseException("Unable to write message header.");
            }
            List<BgpValueType> pathAttr = message.bgpPathAttributes.pathAttributes();
            if (pathAttr != null) {
                Iterator<BgpValueType> listIterator = pathAttr.iterator();

                while (listIterator.hasNext()) {
                    BgpValueType attr = listIterator.next();
                    if (attr instanceof MpReachNlri) {
                        MpReachNlri mpReach = (MpReachNlri) attr;
                        afi = mpReach.afi();
                        safi = mpReach.safi();
                    } else if (attr instanceof MpUnReachNlri) {
                        MpUnReachNlri mpUnReach = (MpUnReachNlri) attr;
                        afi = mpUnReach.afi();
                        safi = mpUnReach.safi();
                    }
                }

                if ((afi == Constants.AFI_FLOWSPEC_VALUE) || (afi == Constants.AFI_VALUE)) {
                    //unfeasible route length
                    cb.writeShort(0);
                }

            }

            if (message.bgpPathAttributes != null) {
                message.bgpPathAttributes.write(cb);
            }

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

    /**
     * Parses NLRI from channel buffer.
     *
     * @param cb channelBuffer
     * @return list of IP Prefix
     * @throws BgpParseException while parsing NLRI
     */
    public static LinkedList<IpPrefix> parseNlri(ChannelBuffer cb)
            throws BgpParseException {
        LinkedList<IpPrefix> nlri = new LinkedList<>();
        while (cb.readableBytes() > 0) {
            int length = cb.readByte();
            IpPrefix ipPrefix;
            if (length == 0) {
                byte[] prefix = new byte[] {0};
                ipPrefix = Validation.bytesToPrefix(prefix, length);
                nlri.add(ipPrefix);
            } else {
                int len = length / BYTE_IN_BITS;
                int reminder = length % BYTE_IN_BITS;
                if (reminder > 0) {
                    len = len + 1;
                }
                if (cb.readableBytes() < len) {
                    Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
                            BgpErrorType.MALFORMED_ATTRIBUTE_LIST,
                            cb.readableBytes());
                }
                byte[] prefix = new byte[len];
                cb.readBytes(prefix, 0, len);
                ipPrefix = Validation.bytesToPrefix(prefix, length);
                nlri.add(ipPrefix);
            }
        }
        return nlri;
    }

    /**
     * Parsing withdrawn routes from channel buffer.
     *
     * @param cb channelBuffer
     * @return list of IP prefix
     * @throws BgpParseException while parsing withdrawn routes
     */
    public static LinkedList<IpPrefix> parseWithdrawnRoutes(ChannelBuffer cb)
            throws BgpParseException {
        LinkedList<IpPrefix> withDrwRoutes = new LinkedList<>();
        while (cb.readableBytes() > 0) {
            int length = cb.readByte();
            IpPrefix ipPrefix;
            if (length == 0) {
                byte[] prefix = new byte[] {0};
                ipPrefix = Validation.bytesToPrefix(prefix, length);
                withDrwRoutes.add(ipPrefix);
            } else {
                int len = length / BYTE_IN_BITS;
                int reminder = length % BYTE_IN_BITS;
                if (reminder > 0) {
                    len = len + 1;
                }
                if (cb.readableBytes() < len) {
                    Validation
                            .validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
                                         BgpErrorType.MALFORMED_ATTRIBUTE_LIST,
                                         cb.readableBytes());
                }
                byte[] prefix = new byte[len];
                cb.readBytes(prefix, 0, len);
                ipPrefix = Validation.bytesToPrefix(prefix, length);
                withDrwRoutes.add(ipPrefix);
            }
        }
        return withDrwRoutes;
    }

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

    @Override
    public BgpType getType() {
        return BgpType.UPDATE;
    }

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

    @Override
    public BgpPathAttributes bgpPathAttributes() {
        return this.bgpPathAttributes;
    }

    @Override
    public List<IpPrefix> withdrawnRoutes() {
        return withdrawnRoutes;
    }

    @Override
    public List<IpPrefix> nlri() {
        return nlri;
    }

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

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(getClass())
                .omitNullValues()
                .add("bgpHeader", bgpHeader)
                .add("withDrawnRoutes", withdrawnRoutes)
                .add("nlri", nlri)
                .add("bgpPathAttributes", bgpPathAttributes)
                .toString();
    }
}
