/*
 * Copyright (c) 2021, 2024, 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.Arena;
import java.lang.foreign.FunctionDescriptor;
import java.lang.foreign.Linker;
import java.lang.foreign.MemoryLayout;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.SegmentAllocator;
import java.lang.foreign.ValueLayout;
import java.lang.invoke.MethodHandle;
import java.lang.reflect.Field;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.function.UnaryOperator;

import jdk.internal.foreign.AbstractMemorySegmentImpl;
import jdk.internal.foreign.StringSupport;
import org.testng.annotations.*;

import static java.lang.foreign.ValueLayout.*;
import static org.testng.Assert.*;

/*
 * @test
 * @modules java.base/jdk.internal.foreign
 * @run testng TestStringEncoding
 */

public class TestStringEncoding {

    @Test
    public void emptySegment() {
        for (Charset charset : standardCharsets()) {
            for (Arena arena : arenas()) {
                try (arena) {
                    var segment = arena.allocate(0);
                    var e = expectThrows(IndexOutOfBoundsException.class, () ->
                            segment.getString(0, charset));
                    assertTrue(e.getMessage().contains("No null terminator found"));
                }
            }
        }
    }

    @Test(dataProvider = "strings")
    public void testStrings(String testString) {
        for (Charset charset : Charset.availableCharsets().values()) {
            if (isStandard(charset)) {
                for (Arena arena : arenas()) {
                    try (arena) {
                        MemorySegment text = arena.allocateFrom(testString, charset);

                        int terminatorSize = "\0".getBytes(charset).length;
                        if (charset == StandardCharsets.UTF_16) {
                            terminatorSize -= 2; // drop BOM
                        }
                        // Note that the JDK's UTF_32 encoder doesn't add a BOM.
                        // This is legal under the Unicode standard, and means the byte order is BE.
                        // See: https://unicode.org/faq/utf_bom.html#gen7

                        int expectedByteLength =
                                testString.getBytes(charset).length +
                                        terminatorSize;

                        assertEquals(text.byteSize(), expectedByteLength);

                        String roundTrip = text.getString(0, charset);
                        if (charset.newEncoder().canEncode(testString)) {
                            assertEquals(roundTrip, testString);
                        }
                    }
                }
            } else {
                assertThrows(IllegalArgumentException.class, () -> Arena.global().allocateFrom(testString, charset));
            }
        }
    }

    @Test(dataProvider = "strings")
    public void testStringsHeap(String testString) {
        for (Charset charset : singleByteCharsets()) {
            for (var arena : arenas()) {
                try (arena) {
                    MemorySegment text = arena.allocateFrom(testString, charset);
                    text = toHeapSegment(text);

                    int expectedByteLength =
                            testString.getBytes(charset).length + 1;

                    assertEquals(text.byteSize(), expectedByteLength);

                    String roundTrip = text.getString(0, charset);
                    if (charset.newEncoder().canEncode(testString)) {
                        assertEquals(roundTrip, testString);
                    }
                }
            }
        }
    }

    MemorySegment toHeapSegment(MemorySegment segment) {
        var heapArray = segment.toArray(JAVA_BYTE);
        return MemorySegment.ofArray(heapArray);
    }

    @Test(dataProvider = "strings")
    public void unboundedSegment(String testString) {
        testModifyingSegment(testString,
                standardCharsets(),
                s -> s.reinterpret(Long.MAX_VALUE),
                UnaryOperator.identity());
    }

    @Test(dataProvider = "strings")
    public void unalignedSegmentSingleByte(String testString) {
        testModifyingSegment(testString,
                singleByteCharsets(),
                s -> s.byteSize() > 1 ? s.asSlice(1) : s,
                s -> s.length() > 0 ? s.substring(1) : s);
    }

    @Test(dataProvider = "strings")
    public void expandedSegment(String testString) {
        try (var arena = Arena.ofConfined()) {
            for (int i = 0; i < Long.BYTES; i++) {
                int extra = i;
                testModifyingSegment(testString,
                        // Single byte charsets
                        standardCharsets(),
                        s -> {
                            var s2 = arena.allocate(s.byteSize() + extra);
                            MemorySegment.copy(s, 0, s2, 0, s.byteSize());
                            return s2;
                        },
                        UnaryOperator.identity());
            }
        }
    }

    public void testModifyingSegment(String testString,
                                     List<Charset> charsets,
                                     UnaryOperator<MemorySegment> segmentMapper,
                                     UnaryOperator<String> stringMapper) {
        for (var charset : charsets) {
            try (Arena arena = Arena.ofConfined()) {
                MemorySegment text = arena.allocateFrom(testString, charset);
                text = segmentMapper.apply(text);
                String roundTrip = text.getString(0, charset);
                String expected = stringMapper.apply(testString);
                if (charset.newEncoder().canEncode(testString)) {
                    assertEquals(roundTrip, expected);
                }
            }
        }
    }

    @Test()
    public void testPeculiarContentSingleByte() {
        Random random = new Random(42);
        for (int len = 7; len < 71; len++) {
            for (var arena : arenas()) {
                try (arena) {
                    var segment = arena.allocate(len, 1);
                    var arr = new byte[len];
                    random.nextBytes(arr);
                    segment.copyFrom(MemorySegment.ofArray(arr));
                    int terminatorIndex = random.nextInt(len);
                    segment.set(ValueLayout.JAVA_BYTE, terminatorIndex, (byte) 0);
                    for (Charset charset : singleByteCharsets()) {
                        var s = segment.getString(0, charset);
                        var ref = referenceImpl(segment, 0, charset);
                        assertEquals(s, ref);
                    }
                }
            }
        }
    }

    @Test(dataProvider = "strings")
    public void testOffset(String testString) {
        if (testString.length() < 3 || !containsOnlyRegularCharacters(testString)) {
            return;
        }
        for (var charset : singleByteCharsets()) {
            for (var arena: arenas()) {
                try (arena) {
                    MemorySegment inSegment = arena.allocateFrom(testString, charset);
                    for (int i = 0; i < 3; i++) {
                        String expected = testString.substring(i);
                        String actual = inSegment.getString(i, charset);
                        assertEquals(actual, expected);
                    }
                }
            }
        }
    }

    private static final MemoryLayout CHAR_POINTER = ADDRESS
            .withTargetLayout(MemoryLayout.sequenceLayout(Long.MAX_VALUE, JAVA_BYTE));
    private static final Linker LINKER = Linker.nativeLinker();
    private static final MethodHandle STRCAT = LINKER.downcallHandle(
            LINKER.defaultLookup().find("strcat").orElseThrow(),
            FunctionDescriptor.of(CHAR_POINTER, CHAR_POINTER, CHAR_POINTER));

    @Test(dataProvider = "strings")
    public void nativeSegFromNativeCall(String testString) {
        String addition = "123";
        try (var arena = Arena.ofConfined()) {
            try {
                var testStringSegment = arena.allocateFrom(testString);
                var additionSegment = arena.allocateFrom(addition);
                var destination = arena.allocate(testStringSegment.byteSize() + additionSegment.byteSize() - 1);
                destination.copyFrom(testStringSegment);

                MemorySegment concatenation = (MemorySegment) STRCAT.invokeExact(destination, arena.allocateFrom(addition));
                var actual = concatenation.getString(0);
                assertEquals(actual, testString + addition);
            } catch (Throwable t) {
                throw new AssertionError(t);
            }
        }
    }

    @Test
    public void segmentationFault() {
        for (int i = 1; i < 18; i++) {
            var size = 1 << i;
            try (var arena = Arena.ofConfined()) {
                var seg = arena.allocate(size, size);
                seg.fill((byte) 1);
                try {
                    var s = seg.getString(0);
                    System.out.println("s.length() = " + s.length());
                } catch (IndexOutOfBoundsException e) {
                    // we will end up here if strlen finds a zero outside the MS
                }
            }
        }
    }

    // This test ensures that we do not address outside the segment even though there
    // are odd bytes at the end.
    @Test(dataProvider = "strings")
    public void offBoundaryTrailingBytes(String testString) {
        if (testString.length() < 3 || !containsOnlyRegularCharacters(testString)) {
            return;
        }
        for (var charset : standardCharsets()) {
            for (var arena: arenas()) {
                try (arena) {
                    MemorySegment strSegment = arena.allocateFrom(testString, charset);
                    // Add an odd byte at the end
                    MemorySegment inSegment = arena.allocate(strSegment.byteSize() + 1);
                    // Make sure there are no null-terminators so that we will try to scan
                    // the entire segment.
                    inSegment.fill((byte) 1);
                    for (int i = 0; i < 4; i++) {
                        final int offset = i;
                        var e = expectThrows(IndexOutOfBoundsException.class, () -> inSegment.getString(offset, charset));
                        assertTrue(e.getMessage().contains("No null terminator found"));
                    }
                }
            }
        }
    }

    private static final int TEST_LENGTH_MAX = 277;

    private Random deterministicRandom() {
        return new Random(42);
    }

    @Test
    public void chunked_strlen_byte() {
        Random random = deterministicRandom();
        for (int skew = 0; skew < Long.BYTES; skew++) {
            for (int len = 0; len < TEST_LENGTH_MAX; len++) {
                try (var arena = Arena.ofConfined()) {
                    var segment = arena.allocate(len + 1 + skew)
                            .asSlice(skew);
                    for (int i = 0; i < len; i++) {
                        byte value;
                        while ((value = (byte) random.nextInt()) == 0) {
                        }
                        segment.setAtIndex(JAVA_BYTE, i, value);
                    }
                    segment.setAtIndex(JAVA_BYTE, len, (byte) 0);
                    for (int j = 0; j < len; j++) {
                        int actual = StringSupport.strlenByte((AbstractMemorySegmentImpl) segment, j, segment.byteSize());
                        assertEquals(actual, len - j);
                    }
                    // Test end offset
                    for (int j = 0; j < len - 1; j++) {
                        final long toOffset = j;
                        expectThrows(IndexOutOfBoundsException.class, () ->
                                StringSupport.strlenByte((AbstractMemorySegmentImpl) segment, 0, toOffset));
                    }
                }
            }
        }
    }

    @Test
    public void chunked_strlen_short() {
        Random random = deterministicRandom();
        for (int skew = 0; skew < Long.BYTES; skew += Short.BYTES) {
            for (int len = 0; len < TEST_LENGTH_MAX; len++) {
                try (var arena = Arena.ofConfined()) {
                    var segment = arena.allocate((len + 1) * Short.BYTES + skew, JAVA_SHORT.byteAlignment())
                            .asSlice(skew);
                    for (int i = 0; i < len; i++) {
                        short value;
                        while ((value = (short) random.nextInt()) == 0) {
                        }
                        segment.setAtIndex(JAVA_SHORT, i, value);
                    }
                    segment.setAtIndex(JAVA_SHORT, len, (short) 0);
                    for (int j = 0; j < len; j++) {
                        int actual = StringSupport.strlenShort((AbstractMemorySegmentImpl) segment, j * Short.BYTES, segment.byteSize());
                        assertEquals(actual, (len - j) * Short.BYTES);
                    }
                }
            }
        }
    }

    @Test
    public void strlen_int() {
        Random random = deterministicRandom();
        for (int skew = 0; skew < Long.BYTES; skew += Integer.BYTES) {
            for (int len = 0; len < TEST_LENGTH_MAX; len++) {
                try (var arena = Arena.ofConfined()) {
                    var segment = arena.allocate((len + 1) * Integer.BYTES + skew, JAVA_INT.byteAlignment())
                            .asSlice(skew);
                    for (int i = 0; i < len; i++) {
                        int value;
                        while ((value = random.nextInt()) == 0) {
                        }
                        segment.setAtIndex(JAVA_INT, i, value);
                    }
                    segment.setAtIndex(JAVA_INT, len, 0);
                    for (int j = 0; j < len; j++) {
                        int actual = StringSupport.strlenInt((AbstractMemorySegmentImpl) segment, j * Integer.BYTES, segment.byteSize());
                        assertEquals(actual, (len - j) * Integer.BYTES);
                    }
                }
            }
        }
    }

    @Test(dataProvider = "charsetsAndSegments")
    public void testStringGetWithCharset(Charset charset, MemorySegment segment) {
        for (int offset = 0 ; offset < Long.BYTES ; offset++) {
            segment.getString(offset, charset);
        }
    }

    @Test(dataProvider = "charsetsAndSegments")
    public void testStringSetWithCharset(Charset charset, MemorySegment segment) {
        for (int offset = 0 ; offset < Long.BYTES ; offset++) {
            segment.setString(offset, "H", charset);
        }
    }

    @Test(dataProvider = "charsetsAndSegments")
    public void testStringAllocateFromWithCharset(Charset charset, MemorySegment segment) {
        for (int offset = 0 ; offset < Long.BYTES ; offset++) {
            SegmentAllocator.prefixAllocator(segment.asSlice(offset)).allocateFrom("H", charset);
        }
    }

    @DataProvider
    public static Object[][] strings() {
        return new Object[][]{
                {"testing"},
                {""},
                {"X"},
                {"12345"},
                {"yen \u00A5"},
                {"snowman \u26C4"},
                {"rainbow \uD83C\uDF08"},
                {"0"},
                {"01"},
                {"012"},
                {"0123"},
                {"01234"},
                {"012345"},
                {"0123456"},
                {"01234567"},
                {"012345678"},
                {"0123456789"}
        };
    }

    public static boolean containsOnlyRegularCharacters(String s) {
        return s.chars()
                .allMatch(c -> Character.isLetterOrDigit((char) c));
    }

    static boolean isStandard(Charset charset) {
        for (Field standardCharset : StandardCharsets.class.getDeclaredFields()) {
            try {
                if (standardCharset.get(null) == charset) {
                    return true;
                }
            } catch (ReflectiveOperationException e) {
                throw new AssertionError(e);
            }
        }
        return false;
    }

    static List<Charset> standardCharsets() {
        return Charset.availableCharsets().values().stream()
                .filter(TestStringEncoding::isStandard)
                .toList();
    }

    List<Charset> singleByteCharsets() {
        return Arrays.asList(StandardCharsets.UTF_8, StandardCharsets.ISO_8859_1, StandardCharsets.US_ASCII);
    }

    static String referenceImpl(MemorySegment segment, long offset, Charset charset) {
        long len = strlen_byte(segment, offset);
        byte[] bytes = new byte[(int) len];
        MemorySegment.copy(segment, JAVA_BYTE, offset, bytes, 0, (int) len);
        return new String(bytes, charset);
    }

    // Reference implementation
    private static int strlen_byte(MemorySegment segment, long start) {
        // iterate until overflow (String can only hold a byte[], whose length can be expressed as an int)
        for (int offset = 0; offset >= 0; offset++) {
            byte curr = segment.get(JAVA_BYTE, start + offset);
            if (curr == 0) {
                return offset;
            }
        }
        throw new IllegalArgumentException("String too large");
    }

    private static List<Arena> arenas() {
        return Arrays.asList(
                Arena.ofConfined(),          // Native memory
                new HeapArena(byte.class),   // Heap memory backed by a byte array
                new HeapArena(short.class),  // Heap memory backed by a short array
                new HeapArena(int.class),    // Heap memory backed by an int array
                new HeapArena(long.class));  // Heap memory backed by a long array
    }

    private static final class HeapArena implements Arena {

        private static final int ELEMENT_SIZE = 1_000;

        private final MemorySegment backingSegment;
        private final SegmentAllocator allocator;

        public HeapArena(Class<?> type) {
            backingSegment = switch (type) {
                case Class<?> c when byte.class.equals(c) -> MemorySegment.ofArray(new byte[ELEMENT_SIZE]);
                case Class<?> c when short.class.equals(c) ->
                        MemorySegment.ofArray(new short[ELEMENT_SIZE]);
                case Class<?> c when int.class.equals(c) ->
                        MemorySegment.ofArray(new int[ELEMENT_SIZE]);
                case Class<?> c when long.class.equals(c) ->
                        MemorySegment.ofArray(new long[ELEMENT_SIZE]);
                default -> throw new IllegalArgumentException(type.toString());
            };
            allocator = SegmentAllocator.slicingAllocator(backingSegment);
        }

        @Override
        public MemorySegment allocate(long byteSize, long byteAlignment) {
            return allocator.allocate(byteSize, byteAlignment);
        }

        @Override
        public MemorySegment.Scope scope() {
            return backingSegment.scope();
        }

        @Override
        public void close() {
            // Do nothing
        }

        @Override
        public String toString() {
            return "HeapArena{" +
                    "type=" + backingSegment.heapBase().orElseThrow().getClass().getName() +
                    '}';
        }
    }

    static MemorySegment[] heapSegments() {
        return new MemorySegment[]{
                MemorySegment.ofArray(new byte[80]),
                MemorySegment.ofArray(new char[40]),
                MemorySegment.ofArray(new short[40]),
                MemorySegment.ofArray(new int[20]),
                MemorySegment.ofArray(new float[20]),
                MemorySegment.ofArray(new long[10]),
                MemorySegment.ofArray(new double[10])
        };
    }

    @DataProvider
    public static Object[][] charsetsAndSegments() {
        List<Object[]> values = new ArrayList<>();
        for (Charset charset : standardCharsets()) {
            for (MemorySegment heapSegment : heapSegments()) {
                values.add(new Object[] { charset, heapSegment });
            }
        }
        return values.toArray(Object[][]::new);
    }
}
