package java2d.color;

import java.awt.color.ColorSpace;
import java.util.concurrent.TimeUnit;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Threads;
import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

@BenchmarkMode({Mode.AverageTime})
@Warmup(iterations = 5, time = 2)
@Measurement(iterations = 5, time = 2)
@Fork(value = 1, jvmArgs = "-XX:-BackgroundCompilation")
@Threads(1)
@State(Scope.Thread)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class OnePixelConvert {

    public static final ColorSpace INSTANCE = ColorSpace.getInstance(
            ColorSpace.CS_sRGB);
    public static final float[] COLOR1 = {0, 0.5f, 1};
    public static final float[] COLOR2 = {0.5f, 0.5f, 0.5f};

    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder().include(
                ".*" + "OnePixelConvert" + ".*").build();
        new Runner(opt).run();
    }

    @Benchmark
    public Object testConvertToRGB() {
        return INSTANCE.toRGB(COLOR1);
    }

    @Benchmark
    public void testConvertToRGBTwice(Blackhole bh) {
        bh.consume(INSTANCE.toRGB(COLOR1));
        bh.consume(INSTANCE.toRGB(COLOR2));
    }

    @Benchmark
    public Object testConvertFromRGB() {
        return INSTANCE.fromRGB(COLOR1);
    }

    @Benchmark
    public void testConvertFromRGBTwice(Blackhole bh) {
        bh.consume(INSTANCE.fromRGB(COLOR1));
        bh.consume(INSTANCE.fromRGB(COLOR2));
    }

    @Benchmark
    public Object testConvertToCIEXYZ() {
        return INSTANCE.toCIEXYZ(COLOR1);
    }

    @Benchmark
    public void testConvertToCIEXYZTwice(Blackhole bh) {
        bh.consume(INSTANCE.toCIEXYZ(COLOR1));
        bh.consume(INSTANCE.toCIEXYZ(COLOR2));
    }

    @Benchmark
    public Object testConvertFromCIEXYZ() {
        return INSTANCE.fromCIEXYZ(COLOR1);
    }

    @Benchmark
    public void testConvertFromCIEXYZTwice(Blackhole bh) {
        bh.consume(INSTANCE.fromCIEXYZ(COLOR1));
        bh.consume(INSTANCE.fromCIEXYZ(COLOR2));
    }

    @Threads(Threads.MAX)
    public static class ThreadsMAX extends OnePixelConvert {
    }

    @BenchmarkMode(Mode.SingleShotTime)
    @Warmup(iterations = 0)
    @Measurement(iterations = 1, batchSize = 1)
    @Fork(10)
    public static class ColdStart extends OnePixelConvert {
    }
}
