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

import org.jboss.netty.buffer.ChannelBuffer;
import org.onosproject.bgpio.exceptions.BgpParseException;
import org.onosproject.bgpio.protocol.BgpFactories;
import org.onosproject.bgpio.protocol.BgpMessage;
import org.onosproject.bgpio.protocol.BgpMessageReader;
import org.onosproject.bgpio.types.BgpErrorType;
import org.onosproject.bgpio.types.BgpHeader;
import org.onosproject.bgpio.util.Validation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Provides BGP messages.
 */
public abstract class BgpMessageVer4 {

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

    static final byte OPEN_MSG_TYPE = 0x1;
    static final byte KEEPALIVE_MSG_TYPE = 0x4;
    static final byte UPDATE_MSG_TYPE = 0x2;
    static final byte NOTIFICATION_MSG_TYPE = 0x3;
    static final int MINIMUM_COMMON_HEADER_LENGTH = 19;
    static final int HEADER_AND_MSG_LEN = 18;
    static final int MAXIMUM_PACKET_LENGTH = 4096;

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

    /**
     * Reader class for reading BGP messages from channel buffer.
     *
     */
    static class Reader implements BgpMessageReader<BgpMessage> {
        @Override
        public BgpMessage readFrom(ChannelBuffer cb, BgpHeader bgpHeader)
                throws BgpParseException {

            if (cb.readableBytes() < MINIMUM_COMMON_HEADER_LENGTH) {
                log.error("Packet should have minimum length.");
                Validation.validateLen(BgpErrorType.MESSAGE_HEADER_ERROR, BgpErrorType.BAD_MESSAGE_LENGTH,
                                       cb.readableBytes());
            }
            if (cb.readableBytes() > MAXIMUM_PACKET_LENGTH) {
                log.error("Packet length should not exceed {}.", MAXIMUM_PACKET_LENGTH);
                Validation.validateLen(BgpErrorType.MESSAGE_HEADER_ERROR, BgpErrorType.BAD_MESSAGE_LENGTH,
                                       cb.readableBytes());
            }
            try {
                // fixed value property version == 4
                byte[] marker = new byte[BgpHeader.MARKER_LENGTH];
                cb.readBytes(marker, 0, BgpHeader.MARKER_LENGTH);
                bgpHeader.setMarker(marker);
                for (int i = 0; i < BgpHeader.MARKER_LENGTH; i++) {
                    if (marker[i] != (byte) 0xff) {
                        throw new BgpParseException(BgpErrorType.MESSAGE_HEADER_ERROR,
                                                    BgpErrorType.CONNECTION_NOT_SYNCHRONIZED, null);
                    }
                }
                short length = cb.readShort();
                if (length > cb.readableBytes() + HEADER_AND_MSG_LEN) {
                    Validation.validateLen(BgpErrorType.MESSAGE_HEADER_ERROR,
                                           BgpErrorType.BAD_MESSAGE_LENGTH, length);
                }
                bgpHeader.setLength(length);
                byte type = cb.readByte();
                bgpHeader.setType(type);
                log.debug("Reading update message of type " + type);

                int len = length - MINIMUM_COMMON_HEADER_LENGTH;
                switch (type) {
                case OPEN_MSG_TYPE:
                    log.debug("OPEN MESSAGE is received");
                    return BgpOpenMsgVer4.READER.readFrom(cb.readBytes(len), bgpHeader);
                case KEEPALIVE_MSG_TYPE:
                    log.debug("KEEPALIVE MESSAGE is received");
                    return BgpKeepaliveMsgVer4.READER.readFrom(cb.readBytes(len), bgpHeader);
                case UPDATE_MSG_TYPE:
                    log.debug("UPDATE MESSAGE is received");
                    return BgpUpdateMsgVer4.READER.readFrom(cb.readBytes(len), bgpHeader);
                case NOTIFICATION_MSG_TYPE:
                    log.debug("NOTIFICATION MESSAGE is received");
                    return BgpNotificationMsgVer4.READER.readFrom(cb.readBytes(len), bgpHeader);
                default:
                    Validation.validateType(BgpErrorType.MESSAGE_HEADER_ERROR, BgpErrorType.BAD_MESSAGE_TYPE, type);
                    return null;
                }
            } catch (IndexOutOfBoundsException e) {
                throw new BgpParseException(BgpErrorType.MESSAGE_HEADER_ERROR,
                                            BgpErrorType.BAD_MESSAGE_LENGTH, null);
            }
        }
    }
}