/*
 * Copyright (c) 2014, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Marcel Valovy - 2.6 - initial implementation
package org.eclipse.persistence.testing.jaxb.beanvalidation;

import com.sun.tools.xjc.Driver;

import org.eclipse.persistence.jaxb.compiler.Generator;

import javax.tools.Diagnostic;
import jakarta.validation.Valid;
import jakarta.validation.constraints.AssertFalse;
import jakarta.validation.constraints.AssertTrue;
import jakarta.validation.constraints.DecimalMax;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.Future;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Past;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;

import org.eclipse.persistence.jaxb.javamodel.reflection.JavaModelImpl;
import org.eclipse.persistence.jaxb.javamodel.reflection.JavaModelInputImpl;

import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlValue;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.OutputStreamWriter;
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;
import javax.tools.StandardLocation;

import static org.eclipse.persistence.testing.jaxb.beanvalidation.ContentComparator.equalsXML;

/**
 * Tests generation of JAXB Facets and Bean Validation annotations during Schemagen and XJC, respectively.
 *
 * @author Marcel Valovy - marcel.valovy@oracle.com
 */
public class BeanValidationBindingsTestCase extends junit.framework.TestCase {

    private static final String GOLDEN_FILE_RESOURCE_PATH = "org/eclipse/persistence/testing/jaxb/beanvalidation/sgen_xjc/golden_file.xsd";
    private static String PATH_TO_SCHEMA_DIRECTORY;
    private static String GOLDEN_FILE_PATH;
    private static String RICH_SCHEMA_PATH;
    private static String CUSTOMIZED_SCHEMA_PATH;
    private static String GENERATED_SCHEMA_PATH;
    private static String TARGET_PATH;
    private static final int DIRS_TO_ROOT = GOLDEN_FILE_RESOURCE_PATH.length() - GOLDEN_FILE_RESOURCE_PATH.replace("/", "").length();

    public BeanValidationBindingsTestCase() {
        try {
            //context class loader and already exists file path is needed to run this test case from within IDE like Eclipse
            PATH_TO_SCHEMA_DIRECTORY = new File(Thread.currentThread().getContextClassLoader().getResource(GOLDEN_FILE_RESOURCE_PATH).toURI()).getParentFile().getAbsolutePath();
            GOLDEN_FILE_PATH = PATH_TO_SCHEMA_DIRECTORY + "/golden_file.xsd";
            RICH_SCHEMA_PATH = PATH_TO_SCHEMA_DIRECTORY + "/rich_schema.xsd";
            CUSTOMIZED_SCHEMA_PATH = PATH_TO_SCHEMA_DIRECTORY + "/customized_schema.xsd";
            GENERATED_SCHEMA_PATH = PATH_TO_SCHEMA_DIRECTORY + "/schema1.xsd";

            File alreadyExistsFile = new File(Thread.currentThread().getContextClassLoader().getResource(GOLDEN_FILE_RESOURCE_PATH).toURI());
            for (int i = 0; i < DIRS_TO_ROOT + 1; i++) {
                alreadyExistsFile = alreadyExistsFile.getParentFile();
            }

            TARGET_PATH = alreadyExistsFile.getAbsolutePath();
        } catch (URISyntaxException e) {
            fail(String.format("Unable to initialize %s test case", BeanValidationBindingsTestCase.class.getName()));
        }
    }

    // Handles error case where no BV annotations would be generated on class fields and would still pass the equality test.
    boolean annotationsGenerated;

    private String pkg;

    @Override
    public void tearDown() throws Exception {
        assertTrue(deleteDir(new File(pkg)));
        //noinspection ResultOfMethodCallIgnored
        new File(GENERATED_SCHEMA_PATH).delete();
    }

    /**
     * A fancy test demonstrating (and testing) that it is possible to perform
     * a round-trip in a lucky case where the XML Schema is identical to the
     * original golden file.
     * In practice, the XJC/Schemagen transformations guarantee only equality
     * of post round-trip schema with the original, not identity.
     * This test should still pass even if changes are done to our code.
     */
    public void testGoldenFileIdentity() throws Throwable {
        pkg = "gf";

        roundTrip(GOLDEN_FILE_PATH, pkg);
        assertTrue(equalsXML(new File(GOLDEN_FILE_PATH), new File(GENERATED_SCHEMA_PATH)));
    }

    /**
     * Tests equality of the original schema and schema after round-trip, with
     * bean validation annotations and facets.
     * Also tests equality of generated Java classes from the original schema
     * and from the schema after round-trip.
     */
    public void testEqualitySchemaAndJava() throws Throwable {
        pkg = "rs";

        Class<?>[] cTenured = roundTrip(RICH_SCHEMA_PATH, pkg);

        xjcGenerateJavaSources(GENERATED_SCHEMA_PATH); // Regenerate the sources.
        compileGeneratedSources(createCompileList(pkg));
        Class<?>[] cYoung = loadCompiledClasses(createLoadList(pkg));

        assertTrue(equalsClasses(cTenured, cYoung));
    }

    /**
     * Tests customizations, i.e. facet customizations + custom facets, i.e.
     * Future, Past, AssertTrue, AssertFalse.
     */
    public void testFacetCustomizationsAndCustomFacets() throws Throwable {
        pkg = "cs";

        xjcGenerateJavaSourcesWithCustomizations(CUSTOMIZED_SCHEMA_PATH);
        compileGeneratedSources(createCompileList(pkg));
        Class<?> custom = loadCompiledClasses(createLoadList(pkg))[0];

        Field generic = custom.getDeclaredField("generic");
        Size s = generic.getAnnotation(Size.class);
        assertEquals(s.message(), "Hello, world!");
        assertEquals(s.groups()[0], BindingTeam.class);
        assertEquals(s.groups()[1], RocketTeam.class);
        assertEquals(s.max(), 4);

        Pattern p1 = generic.getAnnotation(Pattern.List.class).value()[0];
        Pattern p2 = generic.getAnnotation(Pattern.List.class).value()[1];
        assertEquals(p1.message(), p2.message());
        assertTrue(Arrays.equals(p1.groups(), p2.groups()));
        assertEquals(p1.message(), "Hello.");
        assertEquals(p1.groups()[0], Object.class);
        assertEquals(p1.regexp(), "10");

        Future f = generic.getAnnotation(Future.class);
        assertEquals(f.message(), "Welcome to the Future!");
        assertEquals(f.groups()[0], BindingTeam.class);

        Past p = generic.getAnnotation(Past.class);
        assertEquals(p.message(), "Farewell from the ancestors.");
        assertEquals(p.groups()[0], Ancestors.class);

        AssertTrue at = generic.getAnnotation(AssertTrue.class);
        assertEquals(at.message(), "True fan of the team!");
        assertEquals(at.groups()[0], BindingTeam.class);

        AssertFalse af = generic.getAnnotation(AssertFalse.class);
        assertEquals(af.message(), "false");
        assertEquals(af.groups()[0], Object.class);

        // To test a user custom annotation.
        CustomAnnotation xmlKey = generic.getAnnotation(CustomAnnotation.class);
        assertNotNull(xmlKey);
    }

    /**
     * Tests that the XJC detects all facets and generates their respective
     * annotations correctly.
     */
    public void testAllFacetsAndAnnotations() throws Throwable {
        pkg = "rs";

        Class<?>[] c = roundTrip(RICH_SCHEMA_PATH, pkg);
        Class<?> Main = c[0];
        Class<?> Numbers = c[1];
        Class<?> NumberWithHiddenValueAttribute = c[2];
        Class<?> Strings = c[4];

        XmlElement xmlElement;
        Size size;
        DecimalMax decimalMax;
        DecimalMin decimalMin;
        Pattern.List patternList;
        Pattern pattern;

        /* Main.class */
        Field numbers = Main.getDeclaredField("numbers");
        assertNotNull(numbers.getAnnotation(Valid.class));
        assertNotNull(numbers.getAnnotation(NotNull.class));
        xmlElement = numbers.getAnnotation(XmlElement.class);
        assertFalse(xmlElement.nillable());

        Field strings = Main.getDeclaredField("strings");
        size = strings.getAnnotation(Size.class);
        assertTrue(size.min() == 1 && size.max() == 2);
        assertNotNull(strings.getAnnotation(Valid.class));
        assertNotNull(strings.getAnnotation(NotNull.class));
        xmlElement = strings.getAnnotation(XmlElement.class);
        assertFalse(xmlElement.nillable());

        Field unsignedByte = Main.getDeclaredField("unsignedByte");
        decimalMax = unsignedByte.getAnnotation(DecimalMax.class);
        assertEquals(decimalMax.value(), "255");
        assertTrue(decimalMax.inclusive());
        decimalMin = unsignedByte.getAnnotation(DecimalMin.class);
        assertEquals(decimalMin.value(), "0");
        assertTrue(decimalMin.inclusive());

        Field byteArray = Main.getDeclaredField("byteArray");
        size = byteArray.getAnnotation(Size.class);
        assertTrue(size.max() == 18);

        Field someCollection = Main.getDeclaredField("someCollection");
        size = someCollection.getAnnotation(Size.class);
        assertTrue(size.min() == 1);
        assertNotNull(someCollection.getAnnotation(Valid.class));
        assertNotNull(someCollection.getAnnotation(NotNull.class));

        Field optionalElement = Main.getDeclaredField("optionalElement");
        size = optionalElement.getAnnotation(Size.class);
        assertTrue(size.min() == 0);
        assertNotNull(optionalElement.getAnnotation(Valid.class));
        assertNull(optionalElement.getAnnotation(NotNull.class));

        Field optionalElementWithSimpleType = Main.getDeclaredField("optionalElementWithSimpleType");
        assertNull(optionalElementWithSimpleType.getAnnotation(NotNull.class));
        decimalMin = optionalElementWithSimpleType.getAnnotation(DecimalMin.class);
        assertEquals(decimalMin.value(), "1");
        decimalMax = optionalElementWithSimpleType.getAnnotation(DecimalMax.class);
        assertEquals(decimalMax.value(), "31");

        /* Numbers.class */
        Field minInclusive = Numbers.getDeclaredField("minInclusive");
        decimalMin = minInclusive.getAnnotation(DecimalMin.class);
        assertEquals(decimalMin.value(), "1000");
        assertTrue(decimalMin.inclusive());

        Field maxInclusive = Numbers.getDeclaredField("maxInclusive");
        decimalMax = maxInclusive.getAnnotation(DecimalMax.class);
        assertEquals(decimalMax.value(), "1000");
        assertTrue(decimalMax.inclusive());

        Field minExclusive = Numbers.getDeclaredField("minExclusive");
        decimalMin = minExclusive.getAnnotation(DecimalMin.class);
        assertEquals(decimalMin.value(), "0");
        assertFalse(decimalMin.inclusive());

        Field maxExclusive = Numbers.getDeclaredField("maxExclusive");
        decimalMax = maxExclusive.getAnnotation(DecimalMax.class);
        assertEquals(decimalMax.value(), "1000");
        assertFalse(decimalMax.inclusive());

        Field minMaxExclusive = Numbers.getDeclaredField("minMaxExclusive");
        decimalMax = minMaxExclusive.getAnnotation(DecimalMax.class);
        assertEquals(decimalMax.value(), "9223372");
        assertFalse(decimalMax.inclusive());
        decimalMin = minMaxExclusive.getAnnotation(DecimalMin.class);
        assertEquals(decimalMin.value(), "0");
        assertFalse(decimalMin.inclusive());

        /* NumberWithHiddenValueAttribute.class */
        Field value = NumberWithHiddenValueAttribute.getDeclaredField("value");
        assertNotNull(value.getAnnotation(XmlValue.class));
        size = value.getAnnotation(Size.class);
        assertTrue(size.min() == 1 && size.max() == 5);

        Field code = NumberWithHiddenValueAttribute.getDeclaredField("code");
        assertNotNull(code.getAnnotation(NotNull.class));

        Field whatNumber = NumberWithHiddenValueAttribute.getDeclaredField("whatNumber");
        XmlAttribute xmlAttribute = whatNumber.getAnnotation(XmlAttribute.class);
        assertTrue(xmlAttribute.required());

        /* Strings.class */
        Field regexShorthands = Strings.getDeclaredField("regexShorthands");
        patternList = regexShorthands.getAnnotation(Pattern.List.class);
        Pattern[] patterns = patternList.value();
        assertEquals("[:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD]", patterns[0].regexp());
        assertEquals("[^:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD]", patterns[1].regexp());
        assertEquals("[-.0-9:A-Z_a-z\\u00B7\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u203F\\u2040\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD]", patterns[2].regexp());
        assertEquals("[^-.0-9:A-Z_a-z\\u00B7\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u203F\\u2040\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD]", patterns[3].regexp());
        assertEquals("\\p{Nd}", patterns[4].regexp());
        assertEquals("\\P{Nd}", patterns[5].regexp());
        assertEquals("[\\u0009-\\u000D\\u0020\\u0085\\u00A0\\u1680\\u180E\\u2000-\\u200A\\u2028\\u2029\\u202F\\u205F\\u3000]", patterns[6].regexp());
        assertEquals("[^\\u0009-\\u000D\\u0020\\u0085\\u00A0\\u1680\\u180E\\u2000-\\u200A\\u2028\\u2029\\u202F\\u205F\\u3000]", patterns[7].regexp());
        assertEquals("[\\u0009\\u0020\\u00A0\\u1680\\u180E\\u2000-\\u200A\\u202F\\u205F\\u3000]", patterns[8].regexp());
        assertEquals("[^\\u0009\\u0020\\u00A0\\u1680\\u180E\\u2000\\u2001-\\u200A\\u202F\\u205F\\u3000]", patterns[9].regexp());
        assertEquals("[^\\u000A-\\u000D\\u0085\\u2028\\u2029]", patterns[10].regexp());
        assertEquals("(?:(?>\\u000D\\u000A)|[\\u000A\\u000B\\u000C\\u000D\\u0085\\u2028\\u2029])", patterns[11].regexp());

        Field idType = Strings.getDeclaredField("idType");
        pattern = idType.getAnnotation(Pattern.class);
        assertEquals(pattern.regexp(), "[[:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD]-[:]][[-.0-9:A-Z_a-z\\u00B7\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u203F\\u2040\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD]-[:]]*");
        assertTrue(idType.getAnnotation(Size.class).max() == 100);

        Field genericString = Strings.getDeclaredField("genericString");
        assertTrue(genericString.getAnnotation(Size.class).min() == 0);
        assertTrue(genericString.getAnnotation(Size.class).max() == 1024);

        Field maxLength = Strings.getDeclaredField("maxLength");
        assertTrue(maxLength.getAnnotation(Size.class).max() == 1024);

        Field minLength = Strings.getDeclaredField("minLength");
        assertTrue(minLength.getAnnotation(Size.class).min() == 0);
    }

    private Class<?>[] roundTrip(String schemaPath, String pkg) throws Throwable {
        xjcGenerateJavaSources(schemaPath);
        compileGeneratedSources(createCompileList(pkg));
        Class<?>[] classes = loadCompiledClasses(createLoadList(pkg));
        generateSchema(classes); // Generates resource/PATH_TO_SCHEMA_DIRECTORY/schema1.xsd.
        return classes;
    }

    public void xjcGenerateJavaSources(String schemaPath) throws Exception {
        Driver.run(new String[] { schemaPath, "-XBeanVal" }, System.out, System.out);
    }

    public void xjcGenerateJavaSourcesWithCustomizations(String schemaPath) throws Exception {
        Driver.run(new String[] { schemaPath, "-extension", "-XBeanVal" }, System.out, System.out);
    }

    private void generateSchema(Class<?>[] classes) throws FileNotFoundException {
        JavaModelImpl javaModel = new JavaModelImpl(Thread.currentThread().getContextClassLoader());
        JavaModelInputImpl modelInput = new JavaModelInputImpl(classes, javaModel);
        modelInput.setFacets(true);
        Generator gen = new Generator(modelInput);
        gen.generateSchemaFiles(PATH_TO_SCHEMA_DIRECTORY, null);
    }

    private void compileGeneratedSources(File... compileList) throws Exception {
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        DiagnosticCollector<? super JavaFileObject> diag = new DiagnosticCollector<>();
        StandardJavaFileManager fm = compiler.getStandardFileManager(diag, null, null);
        List<File> pathElements = getPath("jdk.module.path");
        if (!pathElements.isEmpty()) {
            //running on module-path:
            fm.setLocation(StandardLocation.MODULE_PATH, pathElements);
            pathElements = getPath("java.class.path");
            if (!pathElements.isEmpty()) {
                fm.setLocation(StandardLocation.CLASS_PATH, pathElements);
            }
        } else {
            //on cp - move everythig to mp
            pathElements = getPath("java.class.path");
            if (!pathElements.isEmpty()) {
                fm.setLocation(StandardLocation.MODULE_PATH, pathElements);
            }
        }
        fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File(TARGET_PATH)));
        Iterable<? extends JavaFileObject> compilationUnits = fm.getJavaFileObjectsFromFiles(Arrays.asList(compileList));
        List<String> options = new ArrayList<>();
        JavaCompiler.CompilationTask task = compiler.getTask(new OutputStreamWriter(System.out), fm, diag, options,
                null, compilationUnits);

        if (!task.call()) {
            for (Diagnostic diagnostic : diag.getDiagnostics()) {
                System.out.format("Error on line %d in %s\n", diagnostic.getLineNumber(), diagnostic);
            }
            fail("Compilation of generated classes failed. See the diagnostics output.");
        }
    }

    private List<File> getPath(String property) {
        List<File> cp = new ArrayList<>();
        String value = System.getProperty(property, "").trim();
        if (!value.isEmpty()) {
            StringTokenizer st = new StringTokenizer(value, File.pathSeparator);
            while (st.hasMoreTokens()) {
                cp.add(new File(st.nextToken()));
            }
        }
        return cp;
    }

    private File[] createCompileList(String pkg) {
        return "cs".equals(pkg)
                ? new File[]{new File(pkg + "/Custom.java"),
                    new File(pkg + "/ObjectFactory.java"),
                    new File(pkg + "/package-info.java")}
                : new File[]{new File(pkg + "/Main.java"),
                    new File(pkg + "/Numbers.java"),
                    new File(pkg + "/NumberWithHiddenValueAttribute.java"),
                    new File(pkg + "/ObjectFactory.java"),
                    new File(pkg + "/package-info.java"),
                    new File(pkg + "/Strings.java")};
    }

    private Class<?>[] loadCompiledClasses(String... loadList) throws Throwable {
        ClassLoader cl = new URLClassLoader(new URL[] {new File(TARGET_PATH).toURI().toURL()},
                Thread.currentThread().getContextClassLoader());
        Class<?>[] loadedClasses = new Class[loadList.length];
        for (int i = 0; i < loadedClasses.length; i++)
            loadedClasses[i] = cl.loadClass(loadList[i]);
        return loadedClasses;
    }

    private String[] createLoadList(String pkg) throws ClassNotFoundException {
        return "cs".equals(pkg)
                ? new String[]{pkg + ".Custom", pkg + ".ObjectFactory" }
                : new String[]{pkg + ".Main", pkg + ".Numbers",
                pkg + ".NumberWithHiddenValueAttribute", pkg + ".ObjectFactory",
                pkg + ".Strings"};
    }

    private boolean equalsClasses(Class<?>[] cTenured, Class<?>[] cYoung) {
        if (cTenured.length != cYoung.length) return false;
        for (int i = 0; i < cTenured.length; i++)
            if (!equalsAnnotations(cTenured[i], cYoung[i])) return false;
        return true;
    }

    private boolean equalsAnnotations(Class<?> c1, Class<?> c2) {
        Field[] f1 = c1.getDeclaredFields();
        Field[] f2 = c2.getDeclaredFields();
        if (f1.length != f2.length) return false;
        for (int i = 0; i<f2.length; i++) {
            Annotation[] a1 = f1[i].getDeclaredAnnotations();
            Annotation[] a2 = f2[i].getDeclaredAnnotations();
            if (!Arrays.equals(a1, a2)) return false;
            // Returns false if no BV annotations were generated.
            if (!annotationsGenerated)
                for (Annotation a : a1)
                    if (a.annotationType().equals(NotNull.class)) {
                        annotationsGenerated = true;
                        break;
                    }
        }
        return annotationsGenerated;
    }

    private static boolean deleteDir(File file) {
        if (file.isDirectory()) {
            String[] children = file.list();
            for (String child : children)
                deleteDir(new File(file, child));
            return file.delete();
        } else
        // The directory is now empty so delete it
        return file.delete();
    }

    public interface BindingTeam{}
    public @interface RocketTeam{}
    public abstract class Ancestors{}
    @Target({ ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    public static @interface CustomAnnotation {
        String value();
    }

}
