/*
 * Copyright (c) 2015, 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.
 */

/*
 * @test
 * @bug 8139829
 * @summary Test access to members of user defined class.
 * @build KullaTesting TestingInputStream ExpectedDiagnostic
 * @run testng/timeout=600 ClassMembersTest
 */

import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;

import javax.tools.Diagnostic;

import jdk.jshell.SourceCodeAnalysis;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.testng.annotations.BeforeMethod;
import jdk.jshell.TypeDeclSnippet;
import static jdk.jshell.Snippet.Status.OVERWRITTEN;
import static jdk.jshell.Snippet.Status.VALID;

public class ClassMembersTest extends KullaTesting {

    @BeforeMethod
    @Override
    public void setUp() {
        setUp(builder -> builder.executionEngine("local"));
    }

    @Test(dataProvider = "memberTestCase")
    public void memberTest(AccessModifier accessModifier, CodeChunk codeChunk, Static isStaticMember, Static isStaticReference) {
        MemberTestCase testCase = new MemberTestCase(accessModifier, codeChunk, isStaticMember, isStaticReference);
        assertEval(testCase.generateSource());
        String expectedMessage = testCase.expectedMessage;
        if (testCase.codeChunk != CodeChunk.CONSTRUCTOR || testCase.isAccessible()) {
            assertEval("A a = new A();");
        }
        if (expectedMessage == null) {
            assertEval(testCase.useCodeChunk());
        } else {
            assertDeclareFail(testCase.useCodeChunk(), expectedMessage);
        }
    }

    private List<String> parseCode(String input) {
        List<String> list = new ArrayList<>();
        SourceCodeAnalysis codeAnalysis = getAnalysis();
        String source = input;
        while (!source.trim().isEmpty()) {
            SourceCodeAnalysis.CompletionInfo info = codeAnalysis.analyzeCompletion(source);
            list.add(info.source());
            source = info.remaining();
        }
        return list;
    }

    @Test(dataProvider = "memberTestCase")
    public void extendsMemberTest(AccessModifier accessModifier, CodeChunk codeChunk, Static isStaticMember, Static isStaticReference) {
        MemberTestCase testCase = new ExtendsMemberTestCase(accessModifier, codeChunk, isStaticMember, isStaticReference);
        String input = testCase.generateSource();
        List<String> ss = parseCode(input);
        assertEval(ss.get(0));
        if (testCase.codeChunk != CodeChunk.CONSTRUCTOR || testCase.isAccessible()) {
            assertEval(ss.get(1));
            assertEval("B b = new B();");
        }
        String expectedMessage = testCase.expectedMessage;
        if (expectedMessage == null) {
            assertEval(testCase.useCodeChunk());
        } else {
            assertDeclareFail(testCase.useCodeChunk(), expectedMessage);
        }
    }

    @Test
    public void interfaceTest() {
        String interfaceSource =
                "interface A {\n" +
                "   default int defaultMethod() { return 1; }\n" +
                "   static int staticMethod() { return 2; }\n" +
                "   int method();\n" +
                "   class Inner1 {}\n" +
                "   static class Inner2 {}\n" +
                "}";
        assertEval(interfaceSource);
        assertEval("A.staticMethod();", "2");
        String classSource =
                "class B implements A {\n" +
                "   public int method() { return 3; }\n" +
                "}";
        assertEval(classSource);
        assertEval("B b = new B();");
        assertEval("b.defaultMethod();", "1");
        assertDeclareFail("B.staticMethod();",
                new ExpectedDiagnostic("compiler.err.cant.resolve.location.args", 0, 14, 1, -1, -1, Diagnostic.Kind.ERROR));
        assertEval("b.method();", "3");
        assertEval("new A.Inner1();");
        assertEval("new A.Inner2();");
        assertEval("new B.Inner1();");
        assertEval("new B.Inner2();");
    }

    @Test
    public void enumTest() {
        String enumSource =
                "enum E {A(\"s\");\n" +
                "   private final String s;\n" +
                "   private E(String s) { this.s = s; }\n" +
                "   public String method() { return s; }\n" +
                "   private String privateMethod() { return s; }\n" +
                "   public static String staticMethod() { return staticPrivateMethod(); }\n" +
                "   private static String staticPrivateMethod() { return \"a\"; }\n" +
                "}";
        assertEval(enumSource);
        assertEval("E a = E.A;", "A");
        assertDeclareFail("a.s;",
                new ExpectedDiagnostic("compiler.err.report.access", 0, 3, 1, -1, -1, Diagnostic.Kind.ERROR));
        assertDeclareFail("new E(\"q\");",
                new ExpectedDiagnostic("compiler.err.enum.cant.be.instantiated", 0, 10, 0, -1, -1, Diagnostic.Kind.ERROR));
        assertEval("a.method();", "\"s\"");
        assertDeclareFail("a.privateMethod();",
                new ExpectedDiagnostic("compiler.err.report.access", 0, 15, 1, -1, -1, Diagnostic.Kind.ERROR));
        assertEval("E.staticMethod();", "\"a\"");
        assertDeclareFail("a.staticPrivateMethod();",
                new ExpectedDiagnostic("compiler.err.report.access", 0, 21, 1, -1, -1, Diagnostic.Kind.ERROR));
        assertDeclareFail("E.method();",
                new ExpectedDiagnostic("compiler.err.non-static.cant.be.ref", 0, 8, 1, -1, -1, Diagnostic.Kind.ERROR));
    }

    @Test(dataProvider = "retentionPolicyTestCase")
    public void annotationTest(RetentionPolicy policy) {
        assertEval("import java.lang.annotation.*;");
        String annotationSource =
                "@Retention(RetentionPolicy." + policy.toString() + ")\n" +
                "@interface A {}";
        assertEval(annotationSource);
        String classSource =
                "@A class C {\n" +
                "   @A C() {}\n" +
                "   @A void f() {}\n" +
                "   @A int f;\n" +
                "   @A class Inner {}\n" +
                "}";
        assertEval(classSource);
        String isRuntimeVisible = policy == RetentionPolicy.RUNTIME ? "true" : "false";
        assertEval("C.class.getAnnotationsByType(A.class).length > 0;", isRuntimeVisible);
        assertEval("C.class.getDeclaredConstructor().getAnnotationsByType(A.class).length > 0;", isRuntimeVisible);
        assertEval("C.class.getDeclaredMethod(\"f\").getAnnotationsByType(A.class).length > 0;", isRuntimeVisible);
        assertEval("C.class.getDeclaredField(\"f\").getAnnotationsByType(A.class).length > 0;", isRuntimeVisible);
        assertEval("C.Inner.class.getAnnotationsByType(A.class).length > 0;", isRuntimeVisible);
    }

    @DataProvider(name = "retentionPolicyTestCase")
    public Object[][] retentionPolicyTestCaseGenerator() {
        List<Object[]> list = new ArrayList<>();
        for (RetentionPolicy policy : RetentionPolicy.values()) {
            list.add(new Object[]{policy});
        }
        return list.toArray(new Object[list.size()][]);
    }

    @DataProvider(name = "memberTestCase")
    public Object[][] memberTestCaseGenerator() {
        List<Object[]> list = new ArrayList<>();
        for (AccessModifier accessModifier : AccessModifier.values()) {
            for (Static isStaticMember : Static.values()) {
                for (Static isStaticReference : Static.values()) {
                    for (CodeChunk codeChunk : CodeChunk.values()) {
                        if (codeChunk == CodeChunk.CONSTRUCTOR && isStaticMember == Static.STATIC) {
                            continue;
                        }
                        list.add(new Object[]{ accessModifier, codeChunk, isStaticMember, isStaticReference });
                    }
                }
            }
        }
        return list.toArray(new Object[list.size()][]);
    }

    public static class ExtendsMemberTestCase extends MemberTestCase {

        public ExtendsMemberTestCase(AccessModifier accessModifier, CodeChunk codeChunk, Static isStaticMember, Static isStaticReference) {
            super(accessModifier, codeChunk, isStaticMember, isStaticReference);
        }

        @Override
        public String getSourceTemplate() {
            return super.getSourceTemplate() + "\n"
                    + "class B extends A {}";
        }

        @Override
        public String errorMessage() {
            if (!isAccessible()) {
                if (codeChunk == CodeChunk.METHOD) {
                    return "compiler.err.cant.resolve.location.args";
                }
                if (codeChunk == CodeChunk.CONSTRUCTOR) {
                    return "compiler.err.cant.resolve.location";
                }
            }
            return super.errorMessage();
        }

        @Override
        public String useCodeChunk() {
            return useCodeChunk("B");
        }
    }

    public static class MemberTestCase {
        public final AccessModifier accessModifier;
        public final CodeChunk codeChunk;
        public final Static isStaticMember;
        public final Static isStaticReference;
        public final String expectedMessage;

        public MemberTestCase(AccessModifier accessModifier, CodeChunk codeChunk, Static isStaticMember,
                              Static isStaticReference) {
            this.accessModifier = accessModifier;
            this.codeChunk = codeChunk;
            this.isStaticMember = isStaticMember;
            this.isStaticReference = isStaticReference;
            this.expectedMessage = errorMessage();
        }

        public String getSourceTemplate() {
            return  "class A {\n" +
                    "    #MEMBER#\n" +
                    "}";
        }

        public boolean isAccessible() {
            return accessModifier != AccessModifier.PRIVATE;
        }

        public String errorMessage() {
            if (!isAccessible()) {
                return "compiler.err.report.access";
            }
            if (codeChunk == CodeChunk.INNER_INTERFACE) {
                return "compiler.err.abstract.cant.be.instantiated";
            }
            if (isStaticMember == Static.STATIC) {
                if (isStaticReference == Static.NO && codeChunk == CodeChunk.INNER_CLASS) {
                    return "compiler.err.qualified.new.of.static.class";
                }
                return null;
            }
            if (isStaticReference == Static.STATIC) {
                if (codeChunk == CodeChunk.CONSTRUCTOR) {
                    return null;
                }
                if (codeChunk == CodeChunk.INNER_CLASS) {
                    return "compiler.err.encl.class.required";
                }
                return "compiler.err.non-static.cant.be.ref";
            }
            return null;
        }

        public String generateSource() {
            return getSourceTemplate().replace("#MEMBER#", codeChunk.generateSource(accessModifier, isStaticMember));
        }

        protected String useCodeChunk(String className) {
            String name = className.toLowerCase();
            switch (codeChunk) {
                case CONSTRUCTOR:
                    return String.format("new %s();", className);
                case METHOD:
                    if (isStaticReference == Static.STATIC) {
                        return String.format("%s.method();", className);
                    } else {
                        return String.format("%s.method();", name);
                    }
                case FIELD:
                    if (isStaticReference == Static.STATIC) {
                        return String.format("%s.field;", className);
                    } else {
                        return String.format("%s.field;", name);
                    }
                case INNER_CLASS:
                    if (isStaticReference == Static.STATIC) {
                        return String.format("new %s.Inner();", className);
                    } else {
                        return String.format("%s.new Inner();", name);
                    }
                case INNER_INTERFACE:
                    return String.format("new %s.Inner();", className);
                default:
                    throw new AssertionError("Unknown code chunk: " + this);
            }
        }

        public String useCodeChunk() {
            return useCodeChunk("A");
        }
    }

    public enum AccessModifier {
        PUBLIC("public"),
        PROTECTED("protected"),
        PACKAGE_PRIVATE(""),
        PRIVATE("private");

        private final String modifier;

        AccessModifier(String modifier) {
            this.modifier = modifier;
        }

        public String getModifier() {
            return modifier;
        }
    }

    public enum Static {
        STATIC("static"), NO("");

        private final String modifier;

        Static(String modifier) {
            this.modifier = modifier;
        }

        public String getModifier() {
            return modifier;
        }
    }

    public enum CodeChunk {
        CONSTRUCTOR("#MODIFIER# A() {}"),
        METHOD("#MODIFIER# int method() { return 10; }"),
        FIELD("#MODIFIER# int field = 10;"),
        INNER_CLASS("#MODIFIER# class Inner {}"),
        INNER_INTERFACE("#MODIFIER# interface Inner {}");

        private final String code;

        CodeChunk(String code) {
            this.code = code;
        }

        public String generateSource(AccessModifier accessModifier, Static isStatic) {
            return code.replace("#MODIFIER#", accessModifier.getModifier() + " " + isStatic.getModifier());
        }
    }
}
