/*
 * Copyright 2016 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.ospf.protocol.ospfpacket;

import org.jboss.netty.buffer.ChannelBuffer;
import org.onlab.packet.Ip4Address;
import org.onosproject.ospf.exceptions.OspfErrorType;
import org.onosproject.ospf.exceptions.OspfParseException;
import org.onosproject.ospf.protocol.ospfpacket.types.DdPacket;
import org.onosproject.ospf.protocol.ospfpacket.types.HelloPacket;
import org.onosproject.ospf.protocol.ospfpacket.types.LsAcknowledge;
import org.onosproject.ospf.protocol.ospfpacket.types.LsRequest;
import org.onosproject.ospf.protocol.ospfpacket.types.LsUpdate;
import org.onosproject.ospf.protocol.util.OspfParameters;
import org.onosproject.ospf.protocol.util.OspfUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A message reader which reads OSPF messages from ChannelBuffer and converts to OspfMessage instances.
 */
public class OspfMessageReader {
    private static final Logger log = LoggerFactory.getLogger(OspfMessageReader.class);

    /**
     * Reads and Converts the channel buffer to OspfMessage instance.
     *
     * @param channelBuffer channel buffer instance.
     * @return OSPF message instance.
     * @throws Exception might throws exception while parsing buffer
     */
    public OspfMessage readFromBuffer(ChannelBuffer channelBuffer)
            throws Exception {

        if (channelBuffer.readableBytes() < OspfUtil.PACKET_MINIMUM_LENGTH) {
            log.error("Packet should have minimum length...");
            throw new OspfParseException(OspfErrorType.MESSAGE_HEADER_ERROR, OspfErrorType.BAD_MESSAGE_LENGTH);
        }

        try {
            OspfPacketHeader ospfHeader = getOspfHeader(channelBuffer);
            int len = ospfHeader.ospfPacLength() - OspfUtil.OSPF_HEADER_LENGTH;

            OspfMessage ospfMessage = null;
            switch (ospfHeader.ospfType()) {
                case OspfParameters.HELLO:
                    ospfMessage = new HelloPacket(ospfHeader);
                    break;
                case OspfParameters.DD:
                    ospfMessage = new DdPacket(ospfHeader);
                    break;
                case OspfParameters.LSREQUEST:
                    ospfMessage = new LsRequest(ospfHeader);
                    break;
                case OspfParameters.LSUPDATE:
                    ospfMessage = new LsUpdate(ospfHeader);
                    break;
                case OspfParameters.LSACK:
                    ospfMessage = new LsAcknowledge(ospfHeader);
                    break;
                default:
                    log.debug("Message Reader[Decoder] - Unknown LSA type..!!!");
                    break;
            }

            if (ospfMessage != null) {
                try {
                    log.debug("{} Received::Message Length :: {} ", ospfMessage.ospfMessageType(),
                              ospfHeader.ospfPacLength());
                    ospfMessage.readFrom(channelBuffer.readBytes(len));
                } catch (Exception e) {
                    throw new OspfParseException(OspfErrorType.OSPF_MESSAGE_ERROR,
                                                 OspfErrorType.BAD_MESSAGE);
                }

            }

            return ospfMessage;
        } catch (Exception e) {
            throw new OspfParseException(OspfErrorType.OSPF_MESSAGE_ERROR,
                                         OspfErrorType.BAD_MESSAGE);
        }
    }

    /**
     * Gets the OSPF packet Header.
     *
     * @param channelBuffer channel buffer instance.
     * @return Ospf Header instance.
     */
    private OspfPacketHeader getOspfHeader(ChannelBuffer channelBuffer) throws Exception {
        OspfPacketHeader ospfPacketHeader = new OspfPacketHeader();

        byte[] sourceIpBytes = new byte[OspfUtil.FOUR_BYTES];
        channelBuffer.readBytes(sourceIpBytes, 0, OspfUtil.FOUR_BYTES);
        Ip4Address sourceIP = Ip4Address.valueOf(sourceIpBytes);

        // Determine ospf version & Packet Type
        int version = channelBuffer.readByte(); //byte 1 is ospf version
        int packetType = channelBuffer.readByte(); //byte 2 is ospf packet type

        // byte 3 & 4 combine is packet length.
        int packetLength = channelBuffer.readShort();

        if (packetLength > channelBuffer.readableBytes() + OspfUtil.FOUR_BYTES) {
            log.error("Packet should have minimum length...");
            throw new OspfParseException(OspfErrorType.MESSAGE_HEADER_ERROR, OspfErrorType.BAD_MESSAGE_LENGTH);
        }

        byte[] tempByteArray = new byte[OspfUtil.FOUR_BYTES];
        channelBuffer.readBytes(tempByteArray, 0, OspfUtil.FOUR_BYTES);
        Ip4Address routerId = Ip4Address.valueOf(tempByteArray);

        tempByteArray = new byte[OspfUtil.FOUR_BYTES];
        channelBuffer.readBytes(tempByteArray, 0, OspfUtil.FOUR_BYTES);
        Ip4Address areaId = Ip4Address.valueOf(tempByteArray);

        int checkSum = channelBuffer.readUnsignedShort();
        int auType = channelBuffer.readUnsignedShort();
        int authentication = (int) channelBuffer.readLong();

        ospfPacketHeader.setSourceIp(sourceIP);
        ospfPacketHeader.setOspfVer(version);
        ospfPacketHeader.setOspftype(packetType);
        ospfPacketHeader.setOspfPacLength(packetLength);
        ospfPacketHeader.setRouterId(routerId);
        ospfPacketHeader.setAreaId(areaId);
        ospfPacketHeader.setChecksum(checkSum);
        ospfPacketHeader.setAuthType(auType);
        ospfPacketHeader.setAuthentication(authentication);

        return ospfPacketHeader;
    }
}