/*
 * 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.net;

import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import org.apache.cassandra.io.util.DataInputPlus;
import org.apache.cassandra.io.util.DataOutputPlus;
import org.apache.cassandra.utils.vint.VIntCoding;
import sun.misc.Unsafe;

import static org.apache.cassandra.net.MessagingService.VERSION_40;
import static org.apache.cassandra.utils.MonotonicClock.Global.approxTime;

abstract class MessageGenerator
{
    final long seed;
    final Random random;

    private MessageGenerator(long seed)
    {
        this.seed = seed;
        this.random = new Random();
    }

    Message.Builder<Object> builder(long id)
    {
        random.setSeed(id ^ seed);
        long now = approxTime.now();

        int expiresInMillis;
        int expiryMask = random.nextInt();
        if (0 == (expiryMask & 0xffff)) expiresInMillis = 2;
        else if (0 == (expiryMask & 0xfff)) expiresInMillis = 10;
        else if (0 == (expiryMask & 0xff)) expiresInMillis = 100;
        else if (0 == (expiryMask & 0xf)) expiresInMillis = 1000;
        else expiresInMillis = 60 * 1000;

        long expiresInNanos = TimeUnit.MILLISECONDS.toNanos((expiresInMillis / 2) + random.nextInt(expiresInMillis / 2));

        return Message.builder(Verb._TEST_2, null)
                      .withId(id)
                      .withCreatedAt(now)
                      .withExpiresAt(now + expiresInNanos); // don't expire for now
    }

    public int uniformInt(int limit)
    {
        return random.nextInt(limit);
    }

    // generate a Message<?> with the provided id and with both id and info encoded in its payload
    abstract Message<?> generate(long id, byte info);
    abstract MessageGenerator copy();

    static final class UniformPayloadGenerator extends MessageGenerator
    {
        final int minSize;
        final int maxSize;
        final byte[] fillWithBytes;
        UniformPayloadGenerator(long seed, int minSize, int maxSize)
        {
            super(seed);
            this.minSize = Math.max(9, minSize);
            this.maxSize = Math.max(9, maxSize);
            this.fillWithBytes = new byte[32];
            random.setSeed(seed);
            random.nextBytes(fillWithBytes);
        }

        Message<?> generate(long id, byte info)
        {
            Message.Builder<Object> builder = builder(id);
            byte[] payload = new byte[minSize + random.nextInt(maxSize - minSize)];
            ByteBuffer wrapped = ByteBuffer.wrap(payload);
            setId(payload, id);
            payload[8] = info;
            wrapped.position(9);
            while (wrapped.hasRemaining())
                wrapped.put(fillWithBytes, 0, Math.min(fillWithBytes.length, wrapped.remaining()));
            builder.withPayload(payload);
            return builder.build();
        }

        MessageGenerator copy()
        {
            return new UniformPayloadGenerator(seed, minSize, maxSize);
        }
    }

    static long getId(byte[] payload)
    {
        return unsafe.getLong(payload, BYTE_ARRAY_BASE_OFFSET);
    }
    static byte getInfo(byte[] payload)
    {
        return payload[8];
    }
    private static void setId(byte[] payload, long id)
    {
        unsafe.putLong(payload, BYTE_ARRAY_BASE_OFFSET, id);
    }

    static class Header
    {
        public final int length;
        public final long id;
        public final byte info;

        Header(int length, long id, byte info)
        {
            this.length = length;
            this.id = id;
            this.info = info;
        }

        public byte[] read(DataInputPlus in, int length, int messagingVersion) throws IOException
        {
            byte[] result = new byte[Math.max(9, length)];
            setId(result, id);
            result[8] = info;
            in.readFully(result, 9, Math.max(0, length - 9));
            return result;
        }
    }

    static Header readHeader(DataInputPlus in, int messagingVersion) throws IOException
    {
        int length = messagingVersion < VERSION_40
                     ? in.readInt()
                     : (int) in.readUnsignedVInt();
        long id = in.readLong();
        if (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN)
            id = Long.reverseBytes(id);
        byte info = in.readByte();
        return new Header(length, id, info);
    }

    static void writeLength(byte[] payload, DataOutputPlus out, int messagingVersion) throws IOException
    {
        if (messagingVersion < VERSION_40)
            out.writeInt(payload.length);
        else
            out.writeUnsignedVInt(payload.length);
    }

    static long serializedSize(byte[] payload, int messagingVersion)
    {
        return payload.length + (messagingVersion < VERSION_40 ? 4 : VIntCoding.computeUnsignedVIntSize(payload.length));
    }

    private static final Unsafe unsafe;
    static
    {
        try
        {
            Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
            field.setAccessible(true);
            unsafe = (sun.misc.Unsafe) field.get(null);
        }
        catch (Exception e)
        {
            throw new AssertionError(e);
        }
    }
    private static final long BYTE_ARRAY_BASE_OFFSET = unsafe.arrayBaseOffset(byte[].class);

}

