/*
 * @author Ranides Atterwim <ranides@gmail.com>
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira.benchmark
 */
package net.ranides.assira.trace;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Random;
import net.ranides.benchmark.app.BenchmarkName;
import net.ranides.benchmark.app.BenchmarkRunner;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Threads;
import org.openjdk.jmh.runner.RunnerException;

@Threads(1)
@State(Scope.Thread)
public class NSTExceptionBenchmark {
    
    private static final String SOMETHING_BAD_HAS_HAPPENED = "Something bad has happened";
    
    private UserException m_cached;
    
    private String m_str;

    @Setup(Level.Iteration)
    public void setup() {
        m_cached = new UserException( SOMETHING_BAD_HAS_HAPPENED );
        final byte[] bytes = new byte[ 100 ];
        new Random().nextBytes( bytes );
        m_str = new String( bytes, StandardCharsets.ISO_8859_1 );
    }

    @Benchmark
    @BenchmarkName("Throw: cache")
    public UserException throwCached() {
        try {
            throw m_cached;
        }
        catch ( UserException cause ) {
            return cause;
        }
    }

    @Benchmark
    @BenchmarkName("Throw: new")
    public UserException throwNewException() {
        try {
            throw new UserException( SOMETHING_BAD_HAS_HAPPENED );
        }
        catch ( UserException cause ) {
            return cause;
        }
    }

    @Benchmark
    @BenchmarkName("Throw: new (no stacktrace)")
    public NSTException0 throwNewNST() {
        try {
            throw new NSTException0( SOMETHING_BAD_HAS_HAPPENED );
        } 
        catch ( NSTException0 cause ) {
            return cause;
        }
    }

    @Benchmark
    @BenchmarkName("Throw: new (classname)")
    public NSTException1 throwNewName() {
        try {
            throw new NSTException1( SOMETHING_BAD_HAS_HAPPENED );
        } 
        catch ( NSTException1 cause ) { 
            return cause;
        }
    }
    
    @Benchmark
    @BenchmarkName("Throw: new (uid)")
    public EQException throwUID() {
        try {
            throw new EQException( SOMETHING_BAD_HAS_HAPPENED );
        } 
        catch ( EQException cause ) { 
            return cause;
        }
    }

    
    @Benchmark
    @BenchmarkName("Construct: new (no stacktrace)")
    public NSTException0 createNST() {
        return new NSTException0( SOMETHING_BAD_HAS_HAPPENED );
    }
    
    @Benchmark
    @BenchmarkName("Construct: new (classname)")
    public NSTException1 createCN() {
        return new NSTException1( SOMETHING_BAD_HAS_HAPPENED );
    }

    @Benchmark
    @BenchmarkName("Construct: new")
    public UserException createException() {
        return new UserException( SOMETHING_BAD_HAS_HAPPENED );
    }
    
    @Benchmark
    @BenchmarkName("Construct: new (uid)")
    public EQException createUID() {
        return new EQException( SOMETHING_BAD_HAS_HAPPENED );
    }

    @Benchmark
    @BenchmarkName("Construct: object")
    public UserObject createUserObject() {
        return new UserObject( m_str );
    }

    private static class UserObject {
        
        private final String m_str;

        private UserObject(String str) {
            this.m_str = str;
        }

        public String getStr() {
            return m_str;
        }
    }
    
    private static class UserAction {
        
        public void run() {
            throw new NSTException1("Hello");
        }
        
    }

    public static void main(String[] args) throws RunnerException, IOException {
        BenchmarkRunner.run(NSTExceptionBenchmark.class);
    }
    
//    public static void main(String[] args) throws NSTException0, UserException {
//        new UserAction().run();
//    }
    
}