package io.quarkus.avro.runtime.graal;

import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;

import org.apache.avro.Schema;
import org.apache.avro.generic.GenericData;
import org.apache.avro.io.DatumReader;
import org.apache.avro.io.ResolvingDecoder;
import org.apache.avro.util.WeakIdentityHashMap;

import com.oracle.svm.core.annotate.Alias;
import com.oracle.svm.core.annotate.RecomputeFieldValue;
import com.oracle.svm.core.annotate.Substitute;
import com.oracle.svm.core.annotate.TargetClass;

@TargetClass(className = "org.apache.avro.generic.GenericDatumReader")
final class Target_org_apache_avro_generic_GenericDatumReader {

    @Alias
    private GenericData data;
    @Alias
    private Schema actual;
    @Alias
    private Schema expected;
    @Alias
    private DatumReader<?> fastDatumReader;
    @Alias
    private ResolvingDecoder creatorResolver;
    @Alias
    @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset)
    private Thread creator;

    @Alias
    @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.FromAlias)
    private static ThreadLocal<Map<Schema, Map<Schema, ResolvingDecoder>>> RESOLVER_CACHE = ThreadLocal.withInitial(
            WeakIdentityHashMap::new);
    @Alias
    @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset)
    private Map<Schema, Class> stringClassCache;
    @Alias
    @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset)
    private Map<Class, Constructor> stringCtorCache;

    @Substitute
    protected Target_org_apache_avro_generic_GenericDatumReader(GenericData data) {
        this.fastDatumReader = null;
        this.creatorResolver = null;
        this.stringClassCache = new IdentityHashMap();
        this.stringCtorCache = new HashMap();
        this.data = data;
        this.creator = Thread.currentThread();
    }

}

class AvroSubstitutions {
}

@@ -148,24 +148,60 @@
 va.util.Map;
+%0Aimport java.util.function.Function;
 %0A%0Aimport org
@@ -594,16 +594,61 @@
 etClass;
+%0Aimport com.oracle.svm.core.jdk.JDK17OrLater;
 %0A%0A@Targe
@@ -1958,16 +1958,1035 @@
   %7D%0A%0A%7D%0A%0A
+@TargetClass(className = %22org.apache.avro.reflect.ReflectionUtil%22, onlyWith = JDK17OrLater.class)%0Afinal class Target_org_apache_avro_reflect_ReflectionUtil %7B%0A%0A    @Substitute%0A    public static %3CV, R%3E Function%3CV, R%3E getConstructorAsFunction(Class%3CV%3E parameterClass, Class%3CR%3E clazz) %7B%0A        // Cannot use the method handle approach as it uses ProtectionDomain which got removed.%0A        try %7B%0A            Constructor%3CR%3E constructor = clazz.getConstructor(parameterClass);%0A            return new Function%3CV, R%3E() %7B%0A                @Override%0A                public R apply(V v) %7B%0A                    try %7B%0A                        return constructor.newInstance(v);%0A                    %7D catch (Exception e) %7B%0A                        throw new IllegalStateException(%22Unable to create new instance for %22 + clazz, e);%0A                    %7D%0A                %7D%0A            %7D;%0A        %7D catch (Throwable t) %7B%0A            // if something goes wrong, do not provide a Function instance%0A            return null;%0A        %7D%0A    %7D%0A%7D%0A%0A
 class Av

Fix Avro substitutions for Java 17