package csa.tiletools.worldgen.heroextant.maptoolkit.util;

import com.google.common.collect.ImmutableList;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

import java.util.Collection;
import java.util.List;

public class Random {

    private final java.util.Random r;

    public Random() {
        r = new java.util.Random();
    }

    public Random(long seed) {
        r = new java.util.Random(seed);
    }

    public long getCurrentSeed()
    {
        byte[] ba0, ba1, bar;
        try
        {
            ByteArrayOutputStream baos = new ByteArrayOutputStream(128);
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(new java.util.Random(0));
            ba0 = baos.toByteArray();
            baos = new ByteArrayOutputStream(128);
            oos = new ObjectOutputStream(baos);
            oos.writeObject(new java.util.Random(-1));
            ba1 = baos.toByteArray();
            baos = new ByteArrayOutputStream(128);
            oos = new ObjectOutputStream(baos);
            oos.writeObject(r);
            bar = baos.toByteArray();
        }
        catch (IOException e)
        {
            throw new RuntimeException("IOException: " + e);
        }
        if (ba0.length != ba1.length || ba0.length != bar.length)
            throw new RuntimeException("bad serialized length");
        int i = 0;
        while (i < ba0.length && ba0[i] == ba1[i])
        {
            i++;
        }
        int j = ba0.length;
        while (j > 0 && ba0[j - 1] == ba1[j - 1])
        {
            j--;
        }
        if (j - i != 6)
            throw new RuntimeException("6 differing bytes not found");
        // The constant 0x5DEECE66DL is from
        // http://download.oracle.com/javase/6/docs/api/java/util/Random.html .
        return ((bar[i] & 255L) << 40 | (bar[i + 1] & 255L) << 32 |
                (bar[i + 2] & 255L) << 24 | (bar[i + 3] & 255L) << 16 |
                (bar[i + 4] & 255L) << 8 | (bar[i + 5] & 255L)) ^ 0x5DEECE66DL;
    }


    public Point nextPoint(int maxX, int maxY) {
        final int x = r.nextInt(maxX);
        final int y = r.nextInt(maxY);
        return new Point(x, y);
    }

    public int nextInt(int minInclusive, int maxInclusive) {
        return minInclusive + r.nextInt(maxInclusive + 1 - minInclusive);
    }

    public <T> T nextChoice(List<T> choices) {
        final int numberOfChoices = choices.size();
        final int i = r.nextInt(numberOfChoices);
        return choices.get(i);
    }

    public <T> T nextChoice(Collection<T> choices) {
        final ImmutableList<T> choicesList = ImmutableList.copyOf(choices);
        return nextChoice(choicesList);
    }

    public boolean nextBoolean() {
        return r.nextBoolean();
    }

    public long nextLong() {
        return r.nextLong();
    }

    public int nextInt(int i) {
        return r.nextInt(i);
    }

    public double nextDouble() {
        return r.nextDouble();
    }

    public float nextFloat() {
        return r.nextFloat();
    }
}
