/*
 * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

import java.lang.foreign.AddressLayout;
import java.lang.foreign.Arena;
import java.lang.foreign.FunctionDescriptor;
import java.lang.foreign.GroupLayout;
import java.lang.foreign.Linker;
import java.lang.foreign.MemoryLayout;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.PaddingLayout;
import java.lang.foreign.SegmentAllocator;
import java.lang.foreign.SequenceLayout;
import java.lang.foreign.StructLayout;
import java.lang.foreign.SymbolLookup;
import java.lang.foreign.UnionLayout;
import java.lang.foreign.ValueLayout;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.invoke.VarHandle;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.function.UnaryOperator;
import java.util.random.RandomGenerator;

import static java.lang.foreign.MemoryLayout.PathElement.groupElement;
import static java.lang.foreign.MemoryLayout.PathElement.sequenceElement;

public class NativeTestHelper {

    public static final boolean IS_WINDOWS = System.getProperty("os.name").startsWith("Windows");

    private static final MethodHandle MH_SAVER;
    private static final RandomGenerator DEFAULT_RANDOM;

    static {
        int seed = Integer.getInteger("NativeTestHelper.DEFAULT_RANDOM.seed", ThreadLocalRandom.current().nextInt());
        System.out.println("NativeTestHelper::DEFAULT_RANDOM.seed = " + seed);
        System.out.println("Re-run with '-DNativeTestHelper.DEFAULT_RANDOM.seed=" + seed + "' to reproduce");
        DEFAULT_RANDOM = new Random(seed);

        try {
            MH_SAVER = MethodHandles.lookup().findStatic(NativeTestHelper.class, "saver",
                    MethodType.methodType(Object.class, Object[].class, List.class, AtomicReference.class, SegmentAllocator.class, int.class));
        } catch (ReflectiveOperationException e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    public static boolean isIntegral(MemoryLayout layout) {
        return layout instanceof ValueLayout valueLayout && isIntegral(valueLayout.carrier());
    }

    static boolean isIntegral(Class<?> clazz) {
        return clazz == byte.class || clazz == char.class || clazz == short.class
                || clazz == int.class || clazz == long.class;
    }

    public static boolean isPointer(MemoryLayout layout) {
        return layout instanceof ValueLayout valueLayout && valueLayout.carrier() == MemorySegment.class;
    }

    public static final Linker LINKER = Linker.nativeLinker();

    // the constants below are useful aliases for C types. The type/carrier association is only valid for 64-bit platforms.

    /**
     * The layout for the {@code bool} C type
     */
    public static final ValueLayout.OfBoolean C_BOOL = (ValueLayout.OfBoolean) LINKER.canonicalLayouts().get("bool");
    /**
     * The layout for the {@code char} C type
     */
    public static final ValueLayout.OfByte C_CHAR = (ValueLayout.OfByte) LINKER.canonicalLayouts().get("char");
    /**
     * The layout for the {@code short} C type
     */
    public static final ValueLayout.OfShort C_SHORT = (ValueLayout.OfShort) LINKER.canonicalLayouts().get("short");
    /**
     * The layout for the {@code int} C type
     */
    public static final ValueLayout.OfInt C_INT = (ValueLayout.OfInt) LINKER.canonicalLayouts().get("int");

    /**
     * The layout for the {@code long long} C type.
     */
    public static final ValueLayout.OfLong C_LONG_LONG = (ValueLayout.OfLong) LINKER.canonicalLayouts().get("long long");
    /**
     * The layout for the {@code float} C type
     */
    public static final ValueLayout.OfFloat C_FLOAT = (ValueLayout.OfFloat) LINKER.canonicalLayouts().get("float");
    /**
     * The layout for the {@code double} C type
     */
    public static final ValueLayout.OfDouble C_DOUBLE = (ValueLayout.OfDouble) LINKER.canonicalLayouts().get("double");
    /**
     * The {@code T*} native type.
     */
    public static final AddressLayout C_POINTER = ((AddressLayout) LINKER.canonicalLayouts().get("void*"))
            .withTargetLayout(MemoryLayout.sequenceLayout(Long.MAX_VALUE, C_CHAR));
    /**
     * The layout for the {@code size_t} C type
     */
    public static final ValueLayout C_SIZE_T = (ValueLayout) LINKER.canonicalLayouts().get("size_t");

    // Common layout shared by some tests
    // struct S_PDI { void* p0; double p1; int p2; };
    public static final MemoryLayout S_PDI_LAYOUT = switch ((int) ValueLayout.ADDRESS.byteSize()) {
        case 8 -> MemoryLayout.structLayout(
            C_POINTER.withName("p0"),
            C_DOUBLE.withName("p1"),
            C_INT.withName("p2"),
            MemoryLayout.paddingLayout(4));
        case 4 -> MemoryLayout.structLayout(
            C_POINTER.withName("p0"),
            C_DOUBLE.withName("p1"),
            C_INT.withName("p2"));
        default -> throw new UnsupportedOperationException("Unsupported address size");
    };

    private static final MethodHandle FREE = LINKER.downcallHandle(
            LINKER.defaultLookup().find("free").get(), FunctionDescriptor.ofVoid(C_POINTER));

    private static final MethodHandle MALLOC = LINKER.downcallHandle(
            LINKER.defaultLookup().find("malloc").get(), FunctionDescriptor.of(C_POINTER, C_LONG_LONG));

    public static void freeMemory(MemorySegment address) {
        try {
            FREE.invokeExact(address);
        } catch (Throwable ex) {
            throw new IllegalStateException(ex);
        }
    }

    public static MemorySegment allocateMemory(long size) {
        try {
            return (MemorySegment) MALLOC.invokeExact(size);
        } catch (Throwable ex) {
            throw new IllegalStateException(ex);
        }
    }

    public static MemorySegment findNativeOrThrow(String name) {
        return SymbolLookup.loaderLookup().find(name).orElseThrow();
    }

    public static MethodHandle downcallHandle(String symbol, FunctionDescriptor desc, Linker.Option... options) {
        return LINKER.downcallHandle(findNativeOrThrow(symbol), desc, options);
    }

    public static MemorySegment upcallStub(Class<?> holder, String name, FunctionDescriptor descriptor) {
        return upcallStub(holder, name, descriptor, Arena.ofAuto());
    }

    public static MemorySegment upcallStub(Class<?> holder, String name, FunctionDescriptor descriptor, Arena arena) {
        try {
            MethodHandle target = MethodHandles.lookup().findStatic(holder, name, descriptor.toMethodType());
            return LINKER.upcallStub(target, descriptor, arena);
        } catch (ReflectiveOperationException e) {
            throw new RuntimeException(e);
        }
    }

    public static TestValue[] genTestArgs(FunctionDescriptor descriptor, SegmentAllocator allocator) {
        return genTestArgs(DEFAULT_RANDOM, descriptor, allocator);
    }

    public static TestValue[] genTestArgs(RandomGenerator random, FunctionDescriptor descriptor, SegmentAllocator allocator) {
        TestValue[] result = new TestValue[descriptor.argumentLayouts().size()];
        for (int i = 0; i < result.length; i++) {
            result[i] = genTestValue(random, descriptor.argumentLayouts().get(i), allocator);
        }
        return result;
    }

    public record TestValue (Object value, Consumer<Object> check) {
        public void check(Object actual) { check.accept(actual); }
    }

    public static TestValue genTestValue(MemoryLayout layout, SegmentAllocator allocator) {
        return genTestValue(DEFAULT_RANDOM, layout, allocator);
    }

    public static TestValue genTestValue(RandomGenerator random, MemoryLayout layout, SegmentAllocator allocator) {
        if (layout instanceof StructLayout struct) {
            MemorySegment segment = allocator.allocate(struct);
            List<Consumer<Object>> fieldChecks = new ArrayList<>();
            for (MemoryLayout fieldLayout : struct.memberLayouts()) {
                if (fieldLayout instanceof PaddingLayout) continue;
                MemoryLayout.PathElement fieldPath = groupElement(fieldLayout.name().orElseThrow());
                fieldChecks.add(initField(random, segment, struct, fieldLayout, fieldPath, allocator));
            }
            return new TestValue(segment, actual -> fieldChecks.forEach(check -> check.accept(actual)));
        } else if (layout instanceof UnionLayout union) {
            MemorySegment segment = allocator.allocate(union);
            List<MemoryLayout> filteredFields = union.memberLayouts().stream()
                                                                     .filter(l -> !(l instanceof PaddingLayout))
                                                                     .toList();
            int fieldIdx = random.nextInt(filteredFields.size());
            MemoryLayout fieldLayout = filteredFields.get(fieldIdx);
            MemoryLayout.PathElement fieldPath = groupElement(fieldLayout.name().orElseThrow());
            Consumer<Object> check = initField(random, segment, union, fieldLayout, fieldPath, allocator);
            return new TestValue(segment, check);
        } else if (layout instanceof SequenceLayout array) {
            MemorySegment segment = allocator.allocate(array);
            List<Consumer<Object>> elementChecks = new ArrayList<>();
            for (int i = 0; i < array.elementCount(); i++) {
                elementChecks.add(initField(random, segment, array, array.elementLayout(), sequenceElement(i), allocator));
            }
            return new TestValue(segment, actual -> elementChecks.forEach(check -> check.accept(actual)));
        } else if (layout instanceof AddressLayout) {
            MemorySegment value = MemorySegment.ofAddress(random.nextLong());
            return new TestValue(value, actual -> assertEquals(actual, value));
        }else if (layout instanceof ValueLayout.OfByte) {
            byte value = (byte) random.nextInt();
            return new TestValue(value, actual -> assertEquals(actual, value));
        } else if (layout instanceof ValueLayout.OfShort) {
            short value = (short) random.nextInt();
            return new TestValue(value, actual -> assertEquals(actual, value));
        } else if (layout instanceof ValueLayout.OfChar) {
            char value = (char) random.nextInt();
            return new TestValue(value, actual -> assertEquals(actual, value));
        } else if (layout instanceof ValueLayout.OfInt) {
            int value = random.nextInt();
            return new TestValue(value, actual -> assertEquals(actual, value));
        } else if (layout instanceof ValueLayout.OfLong) {
            long value = random.nextLong();
            return new TestValue(value, actual -> assertEquals(actual, value));
        } else if (layout instanceof ValueLayout.OfFloat) {
            float value = random.nextFloat();
            return new TestValue(value, actual -> assertEquals(actual, value));
        } else if (layout instanceof ValueLayout.OfDouble) {
            double value = random.nextDouble();
            return new TestValue(value, actual -> assertEquals(actual, value));
        }

        throw new IllegalStateException("Unexpected layout: " + layout);
    }

    private static Consumer<Object> initField(RandomGenerator random, MemorySegment container, MemoryLayout containerLayout,
                                              MemoryLayout fieldLayout, MemoryLayout.PathElement fieldPath,
                                              SegmentAllocator allocator) {
        TestValue fieldValue = genTestValue(random, fieldLayout, allocator);
        Consumer<Object> fieldCheck = fieldValue.check();
        if (fieldLayout instanceof GroupLayout || fieldLayout instanceof SequenceLayout) {
            UnaryOperator<MemorySegment> slicer = slicer(containerLayout, fieldPath);
            MemorySegment slice = slicer.apply(container);
            slice.copyFrom((MemorySegment) fieldValue.value());
            return actual -> fieldCheck.accept(slicer.apply((MemorySegment) actual));
        } else {
            VarHandle accessor = containerLayout.varHandle(fieldPath);
            //set value
            accessor.set(container, 0L, fieldValue.value());
            return actual -> fieldCheck.accept(accessor.get((MemorySegment) actual, 0L));
        }
    }

    private static UnaryOperator<MemorySegment> slicer(MemoryLayout containerLayout, MemoryLayout.PathElement fieldPath) {
        MethodHandle slicer = containerLayout.sliceHandle(fieldPath);
        return container -> {
              try {
                return (MemorySegment) slicer.invokeExact(container, 0L);
            } catch (Throwable e) {
                throw new IllegalStateException(e);
            }
        };
    }

    private static void assertEquals(Object actual, Object expected) {
        if (actual.getClass() != expected.getClass()) {
            throw new AssertionError("Type mismatch: " + actual.getClass() + " != " + expected.getClass());
        }
        if (!actual.equals(expected)) {
            throw new AssertionError("Not equal: " + actual + " != " + expected);
        }
    }

    /**
     * Make an upcall stub that saves its arguments into the given 'ref' array
     *
     * @param fd function descriptor for the upcall stub
     * @param capturedArgs box to save arguments in
     * @param arena allocator for making copies of by-value structs
     * @param retIdx the index of the argument to return
     * @return return the upcall stub
     */
    public static MemorySegment makeArgSaverCB(FunctionDescriptor fd, Arena arena,
                                               AtomicReference<Object[]> capturedArgs, int retIdx) {
        MethodHandle target = MethodHandles.insertArguments(MH_SAVER, 1, fd.argumentLayouts(), capturedArgs, arena, retIdx);
        target = target.asCollector(Object[].class, fd.argumentLayouts().size());
        target = target.asType(fd.toMethodType());
        return LINKER.upcallStub(target, fd, arena);
    }

    private static Object saver(Object[] o, List<MemoryLayout> argLayouts, AtomicReference<Object[]> ref, SegmentAllocator allocator, int retArg) {
        for (int i = 0; i < o.length; i++) {
            if (argLayouts.get(i) instanceof GroupLayout gl) {
                MemorySegment ms = (MemorySegment) o[i];
                MemorySegment copy = allocator.allocate(gl);
                copy.copyFrom(ms);
                o[i] = copy;
            }
        }
        ref.set(o);
        return retArg != -1 ? o[retArg] : null;
    }
}
