package io.quarkus.kafka.client.runtime.graal;

import static org.apache.kafka.common.record.CompressionType.GZIP;
import static org.apache.kafka.common.record.CompressionType.NONE;

import java.lang.invoke.MethodHandle;
import java.util.List;
import java.util.Map;
import java.util.function.BooleanSupplier;

import org.apache.kafka.common.metrics.JmxReporter;
import org.apache.kafka.common.metrics.KafkaMetric;
import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.record.CompressionType;
import org.apache.kafka.common.utils.AppInfoParser;
import org.graalvm.home.Version;

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;

/**
 * Here is where surgery happens
 * * Remove Snappy if not available (require GraalVM 21+).
 * * Remove JMX
 */

@TargetClass(value = CompressionType.class, innerClass = "SnappyConstructors", onlyWith = GraalVM20OrEarlier.class)
final class SubstituteSnappy {

    @Alias
    @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset)
    static MethodHandle INPUT = null;

    @Alias
    @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset)
    static MethodHandle OUTPUT = null;

}

final class GraalVM20OrEarlier implements BooleanSupplier {

    @Override
    public boolean getAsBoolean() {
        return Version.getCurrent().compareTo(21) < 0;
    }
}

@TargetClass(value = CompressionType.class, onlyWith = GraalVM20OrEarlier.class)
final class FixEnumAccess {

    @Substitute
    public static CompressionType forName(String name) {
        if (NONE.name.equals(name)) {
            return NONE;
        } else if (GZIP.name.equals(name)) {
            return GZIP;
        } else {
            throw new IllegalArgumentException("Unknown  or unsupported compression name: " + name);
        }
    }

    @Substitute
    public static CompressionType forId(int id) {
        switch (id) {
            case 0:
                return NONE;
            case 1:
                return GZIP;
            default:
                throw new IllegalArgumentException("Unknown or unsupported compression type id: " + id);
        }
    }
}

@TargetClass(value = AppInfoParser.class)
final class RemoveJMXAccess {

    @Substitute
    public static synchronized void registerAppInfo(String prefix, String id, Metrics metrics, long nowMs) {

    }

    @Substitute
    public static synchronized void unregisterAppInfo(String prefix, String id, Metrics metrics) {

    }

}

@TargetClass(value = JmxReporter.class)
final class JMXReporting {

    @Substitute
    public void reconfigure(Map<String, ?> configs) {

    }

    @Substitute
    public void init(List<KafkaMetric> metrics) {

    }

    @Substitute
    public void metricChange(KafkaMetric metric) {

    }

    @Substitute
    public void metricRemoval(KafkaMetric metric) {

    }

    @Substitute
    public void close() {
    }

}

@@ -180,46 +180,8 @@
 E;%0A%0A
-import java.lang.invoke.MethodHandle;%0A
 impo
@@ -199,16 +199,16 @@
 l.List;%0A
+
 import j
@@ -562,108 +562,8 @@
 n;%0A%0A
-import com.oracle.svm.core.annotate.Alias;%0Aimport com.oracle.svm.core.annotate.RecomputeFieldValue;%0A
 impo
@@ -777,388 +777,8 @@
 */%0A%0A
-@TargetClass(value = CompressionType.class, innerClass = %22SnappyConstructors%22, onlyWith = GraalVM20OrEarlier.class)%0Afinal class SubstituteSnappy %7B%0A%0A    @Alias%0A    @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset)%0A    static MethodHandle INPUT = null;%0A%0A    @Alias%0A    @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset)%0A    static MethodHandle OUTPUT = null;%0A%0A%7D%0A%0A
 fina
@@ -1045,21 +1045,24 @@
 ass 
-FixEnumAccess
+SubstituteSnappy
  %7B%0A%0A

Remove obsolete substitution for kafka snappy