package org.spoofax.jsglr2.benchmark.jsglr2;

import static org.spoofax.jsglr2.JSGLR2Variant.Preset.incremental;
import static org.spoofax.jsglr2.JSGLR2Variant.Preset.standard;

import java.util.*;

import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Setup;
import org.spoofax.jsglr2.JSGLR2ImplementationWithCache;
import org.spoofax.jsglr2.benchmark.jsglr2.util.JSGLR2MultiParser;
import org.spoofax.jsglr2.benchmark.jsglr2.util.JSGLR2PersistentCache;
import org.spoofax.jsglr2.integration.IntegrationVariant;
import org.spoofax.jsglr2.parseforest.IParseForest;
import org.spoofax.jsglr2.parser.ParseException;
import org.spoofax.jsglr2.testset.testinput.IncrementalStringInput;

public abstract class JSGLR2BenchmarkIncremental extends JSGLR2Benchmark<String[], IncrementalStringInput> {

    public enum ParserType {
        Batch(false, new IntegrationVariant(standard.variant)),
        Incremental(true, new IntegrationVariant(incremental.variant)),
        IncrementalNoCache(false, new IntegrationVariant(incremental.variant));

        boolean setupCache;
        IntegrationVariant integrationVariant;

        ParserType(boolean setupCache, IntegrationVariant integrationVariant) {
            this.setupCache = setupCache;
            this.integrationVariant = integrationVariant;
        }
    }

    @Param({ "Batch", "Incremental", "IncrementalNoCache" }) public ParserType parserType;

    @Param({ "-1" }) public int i;

    @Override protected IntegrationVariant variant() {
        return parserType.integrationVariant;
    }

    // Only used for parsing-only benchmarks
    Map<IncrementalStringInput, String> prevString = new HashMap<>();
    // Only used for parsing-only benchmarks
    Map<IncrementalStringInput, IParseForest> prevParse = new HashMap<>();
    // Only used for parsing-and-imploding benchmarks
    Map<IncrementalStringInput, JSGLR2PersistentCache<?, ?, ?, ?, ?, ?>> prevCacheImpl = new HashMap<>();
    // Only used for parsing-and-imploding benchmarks
    JSGLR2MultiParser<?> jsglr2MultiParser;

    Map<IncrementalStringInput, String[]> uniqueInputs = new HashMap<>();

    protected boolean shouldSetupCache() {
        return parserType.setupCache && i > 0;
    }

    @Setup public void setupCache() throws ParseException {
        if(implode())
            jsglr2MultiParser = new JSGLR2MultiParser<>(jsglr2);
        if(i == -2) {
            for(IncrementalStringInput input : inputs) {
                List<String> res = new ArrayList<>();
                String prev = null;
                for(String s : input.content) {
                    if(!Objects.equals(prev, s)) {
                        res.add(s);
                        prev = s;
                    }
                }
                uniqueInputs.put(input, res.toArray(new String[0]));
            }
        }
        if(shouldSetupCache()) {
            for(IncrementalStringInput input : inputs) {
                String content = input.content[i - 1];
                if(content == null)
                    continue;
                if(!implode()) {
                    prevString.put(input, content);
                    prevParse.put(input, jsglr2.parser.parseUnsafe(content, null));
                } else {
                    @SuppressWarnings({ "rawtypes", "unchecked" }) JSGLR2PersistentCache impl =
                        new JSGLR2PersistentCache<>(((JSGLR2ImplementationWithCache) jsglr2), content);
                    prevCacheImpl.put(input, impl);
                }
            }
        }
    }

}

@@ -43,140 +43,8 @@
 2;%0A%0A
-import static org.spoofax.jsglr2.JSGLR2Variant.Preset.incremental;%0Aimport static org.spoofax.jsglr2.JSGLR2Variant.Preset.standard;%0A%0A
 impo
@@ -59,16 +59,16 @@
 util.*;%0A
+
 %0Aimport 
@@ -567,16 +567,74 @@
 Input;%0A%0A
+import static org.spoofax.jsglr2.JSGLR2Variant.Preset.*;%0A%0A
 public a
@@ -820,32 +820,99 @@
 dard.variant)),%0A
+        Elkhound(false, new IntegrationVariant(elkhound.variant)),%0A
         Incremen
@@ -1317,24 +1317,24 @@
    %7D%0A    %7D%0A%0A
-
     @Param(%7B
@@ -1342,16 +1342,28 @@
 %22Batch%22,
+ %22Elkhound%22,
  %22Increm

Add Elkhound to incremental benchmarks