/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.cassandra.streaming.messages;

import java.io.IOException;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;

import org.apache.cassandra.io.util.DataOutputStreamPlus;
import org.apache.cassandra.streaming.StreamSession;

/**
 * StreamMessage is an abstract base class that every messages in streaming protocol inherit.
 *
 * Every message carries message type({@link Type}) and streaming protocol version byte.
 */
public abstract class StreamMessage
{
    /** Streaming protocol version */
    public static final int VERSION_20 = 2;
    public static final int VERSION_22 = 3;
    public static final int VERSION_30 = 4;
    public static final int CURRENT_VERSION = VERSION_30;

    public static void serialize(StreamMessage message, DataOutputStreamPlus out, int version, StreamSession session) throws IOException
    {
        ByteBuffer buff = ByteBuffer.allocate(1);
        // message type
        buff.put(message.type.type);
        buff.flip();
        out.write(buff);
        message.type.outSerializer.serialize(message, out, version, session);
    }

    public static StreamMessage deserialize(ReadableByteChannel in, int version, StreamSession session) throws IOException
    {
        ByteBuffer buff = ByteBuffer.allocate(1);
        int readBytes = in.read(buff);
        if (readBytes > 0)
        {
            buff.flip();
            Type type = Type.get(buff.get());
            return type.inSerializer.deserialize(in, version, session);
        }
        else if (readBytes == 0)
        {
            // input socket buffer was not filled yet
            return null;
        }
        else
        {
            // possibly socket gets closed
            throw new SocketException("End-of-stream reached");
        }
    }

    /** StreamMessage serializer */
    public static interface Serializer<V extends StreamMessage>
    {
        V deserialize(ReadableByteChannel in, int version, StreamSession session) throws IOException;
        void serialize(V message, DataOutputStreamPlus out, int version, StreamSession session) throws IOException;
    }

    /** StreamMessage types */
    public static enum Type
    {
        PREPARE(1, 5, PrepareMessage.serializer),
        FILE(2, 0, IncomingFileMessage.serializer, OutgoingFileMessage.serializer),
        RECEIVED(3, 4, ReceivedMessage.serializer),
        RETRY(4, 4, RetryMessage.serializer),
        COMPLETE(5, 1, CompleteMessage.serializer),
        SESSION_FAILED(6, 5, SessionFailedMessage.serializer);

        public static Type get(byte type)
        {
            for (Type t : Type.values())
            {
                if (t.type == type)
                    return t;
            }
            throw new IllegalArgumentException("Unknown type " + type);
        }

        private final byte type;
        public final int priority;
        public final Serializer<StreamMessage> inSerializer;
        public final Serializer<StreamMessage> outSerializer;

        @SuppressWarnings("unchecked")
        private Type(int type, int priority, Serializer serializer)
        {
            this(type, priority, serializer, serializer);
        }

        @SuppressWarnings("unchecked")
        private Type(int type, int priority, Serializer inSerializer, Serializer outSerializer)
        {
            this.type = (byte) type;
            this.priority = priority;
            this.inSerializer = inSerializer;
            this.outSerializer = outSerializer;
        }
    }

    public final Type type;

    protected StreamMessage(Type type)
    {
        this.type = type;
    }

    /**
     * @return priority of this message. higher value, higher priority.
     */
    public int getPriority()
    {
        return type.priority;
    }
}
