/*   Copyright 2004 The Apache Software Foundation
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package misc.detailed;

import misc.common.JiraTestBase;
import org.apache.xmlbeans.*;
import org.apache.xmlbeans.impl.tool.Parameters;
import org.apache.xmlbeans.impl.tool.SchemaCompiler;
import org.apache.xmlbeans.impl.xb.xsdschema.SchemaDocument;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import xmlbeans48.FeedInfoType;

import javax.xml.namespace.QName;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

import static org.junit.jupiter.api.Assertions.*;

public class JiraRegression1_50Test extends JiraTestBase {

    /*
     * [XMLBEANS-2] Problem with XmlError.forObject(String,int,XmlObject)
     */
    @Test
    void test_jira_xmlbeans02() throws Exception {
        StringBuilder xmlstringbuf = new StringBuilder("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
        xmlstringbuf.append("<test>");
        xmlstringbuf.append("<testchild attr=\"abcd\"> Jira02 </testchild>");
        xmlstringbuf.append("</test>");

        List<XmlError> errors = new ArrayList<>();
        XmlOptions options = new XmlOptions().setErrorListener(errors);
        try {
            XmlObject myxmlobj = XmlObject.Factory.parse(xmlstringbuf.toString(), options);
            try (XmlCursor cur = myxmlobj.newCursor()) {
                XmlError xmlerr = XmlError.forObject("This is my custom error message", XmlError.SEVERITY_ERROR, myxmlobj);

                // call an API on the cursor : verification of cursor not being disposed
                System.out.println("Cursor Text Value: " + cur.getTextValue());
            }
        } catch (XmlException ignored) {
        }

        hasSevereError(errors);
    }

    /*
     * [XMLBEANS-4] xs:decimal size greater than 18 results in uncompilable java code
     */
    @Test
    void test_jira_xmlbeans04() {
        List<XmlError> errors = new ArrayList<>();

        Parameters params = new Parameters();
        params.setXsdFiles(new File(scompTestFilesRoot + "xmlbeans_04.xsd_"));
        params.setErrorListener(errors);
        params.setSrcDir(schemaCompSrcDir);
        params.setClassesDir(schemaCompClassesDir);

        SchemaCompiler.compile(params);
        assertFalse(hasSevereError(errors));
    }


    /*
     * [XMLBEANS-9] Null Pointer Exception when running validate from cmd line
     */
    @Test
    @Disabled("no shell tests on junit")
    public void test_jira_xmlbeans09() throws Exception {
        // Exec validate script from cmd line - Refer xmlbeans_09.xsd, xmlbeans_09.xml

        StringBuilder sb = new StringBuilder(" ");
        sb.append(System.getProperty("xbean.rootdir") + P + "bin" + P + "validate.cmd ");
        sb.append(scompTestFilesRoot + "xmlbeans_09.xsd_" + " " + scompTestFilesRoot + "xmlbeans_09.xml");
        Process validator_proc = Runtime.getRuntime().exec(sb.toString());

        System.out.println("cmd:" + sb);
        BufferedInputStream inbuf = new BufferedInputStream(validator_proc.getInputStream());
        BufferedReader reader = new BufferedReader(new InputStreamReader(inbuf));
        String eachline = reader.readLine();

        while (reader.readLine() != null) {
            System.out.println("output: " + eachline);
        }
    }

    /*
     * [XMLBEANS-11]: Calling getUnionMemberTypes() on SchemaType for non-union types results in NullPointerException
     * status : fixed
     */
    @Test
    void test_jira_xmlbeans11() throws Exception {

        String xsdAsString =
            "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" + " <!-- W3C Schema generated by XML Spy v4.3 U (http://www.xmlspy.com)\n" +
            "  --> \n" +
            " <xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" elementFormDefault=\"qualified\">\n" +
            "   <xs:simpleType name=\"restrictsString\">\n" +
            "      <xs:restriction base=\"xs:string\">\n" +
            "          <xs:length value=\"10\" /> \n" +
            "      </xs:restriction>\n" +
            "    </xs:simpleType>\n" +
            "  </xs:schema>";

        // load schema file as SchemaDocument XmlObject
        SchemaDocument sd = SchemaDocument.Factory.parse(xsdAsString);

        // compile loaded XmlObject
        SchemaTypeSystem sts = XmlBeans.compileXsd((XmlObject[]) Collections.singletonList(sd).toArray(new XmlObject[]{}),
            XmlBeans.getContextTypeLoader(),
            new XmlOptions());
        sts.resolve();

        SchemaType[] st = sts.globalTypes();

        System.out.println("NUMBER OF GLOBAL TYPES: " + st.length);

        // check if it is union type
        for (SchemaType schemaType : st) {
            System.out.println("IS UNION TYPE: " + (schemaType.getUnionMemberTypes() != null));
        }
    }

    /*
     * [XMLBEANS-14]: newDomNode() throws NullPointerException
     */
    @Test
    void test_jira_xmlbeans14() throws Exception {
        XmlObject xObj = XmlObject.Factory.parse("<Baz/>");
        // add element
        try (XmlCursor xCursor = xObj.newCursor()) {
            xCursor.toFirstContentToken();
            xCursor.insertElementWithText(new QName("Some uri", "SomeName"), "SomeValue");
            xCursor.insertElementWithText(new QName("Some uri", "SomeName1"), "SomeValue1");
        }

        // debug
        xObj.save(System.out);

        // throws npe in v1
        xObj.newDomNode();

    }


    /*
     * [XMLBEANS-16]: newDomNode creates a DOM with empty strings for namespace URIs for unprefixed
     * attributes (rather than null)
     * status : fails with crimson and not with Xerces
     */
    @Test
    @Disabled("still happens with current xerces 2.11")
    public void test_jira_xmlbeans16() throws Exception {
        String sb =
            "<?xml version='1.0'?>\n" +
            "<test noprefix='nonamespace' \n" +
            "      ns:prefix='namespace' \n" +
            "      xmlns:ns='http://xml.apache.org/xmlbeans'>value</test>";

        // Parse it using XMLBeans
        XmlObject xdoc = XmlObject.Factory.parse(sb);

        // Convert to a DOM Element
        Element firstChild = (Element) xdoc.newDomNode().getFirstChild();

        // We expect to find a null namespace for the first attribute and 'ns' for the second
        NamedNodeMap attributes = firstChild.getAttributes();
        System.out.println("Prefix for attr noprefix is:" + attributes.getNamedItem("noprefix").getPrefix() + ":");
        assertNull(attributes.getNamedItem("noprefix").getPrefix(), "Expected null namespace for attribute noprefix");
        assertEquals("ns", attributes.getNamedItem("ns:prefix").getPrefix(), "Wrong namespace for attribute prefix");

        // We should be able to lookup 'prefix' by specifying the appropriate URI
        String prefix = firstChild.getAttributeNS("http://xml.apache.org/xmlbeans", "prefix");
        assertEquals("namespace", prefix, "Wrong value for prefixed attribute");

        // And 'noprefix' by specifying a null namespace URI
        String noprefix = firstChild.getAttributeNS(null, "noprefix");
        assertEquals("nonamespace", noprefix, "Wrong value for unprefixed attribute"); // This assertion fails under Crimson

    }

    /*
     * [XMLBEANS-33]:  insertions occur in improper order when subclassing schema types
     */
    @Test
    void test_jira_xmlbeans33() throws Exception {

        xbeansJira33B.SubjectType subject =
            xbeansJira33B.SubjectType.Factory.newInstance();
        subject.addNewIDPProvidedNameIdentifier();
        subject.addNewSubjectConfirmation().addConfirmationMethod("foo");
        subject.addNewNameIdentifier();
        XmlOptions options = new XmlOptions();
        List<XmlError> list = new ArrayList<>();
        options.setErrorListener(list);

        boolean bResult = subject.validate(options);
        System.out.println(bResult ? "valid" : "invalid");

        // print out errors
        for (XmlError xmlError : list) {
            System.out.println("Validation Error : " + xmlError);
        }
        assertTrue(bResult, "Validation Failed, should pass");

    }

    /*
     * [XMLBEANS-34]:  error compiling classes when using a schema with a redefined subelement
     */
    @Test
    void test_jira_xmlbeans34() throws Exception {
        List<XmlError> errors = new ArrayList<>();

        Parameters params = new Parameters();
        params.setXsdFiles(new File(scompTestFilesRoot + "xmlbeans_34b.xsd_"));
        params.setErrorListener(errors);
        params.setSrcDir(schemaCompSrcDir);
        params.setClassesDir(schemaCompClassesDir);
        params.setDownload(true);
        params.setNoPvr(true);

        SchemaCompiler.compile(params);
        assertFalse(hasSevereError(errors));
    }


    /**
     * BUGBUG: [XMLBEANS-38]
     * [XMLBEANS-38]   Does not support xs:key (keyRef NoIllegalEntries)
     */
    @Disabled
    public void test_jira_xmlbeans38() throws Exception {
        String keyrefXSD =
            "<?xml version=\"1.0\"?>" +
            "<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">" +
            "<xsd:element name=\"supermarket\">" +
            "<xsd:complexType>" +
            "<xsd:sequence> " +
            "<xsd:element name=\"aisle\" maxOccurs=\"unbounded\"> \n" +
            "<xsd:complexType> " +
            "<xsd:sequence>" +
            "<xsd:element name=\"item\" maxOccurs=\"unbounded\"> \n" +
            "<xsd:complexType> " +
            "<xsd:simpleContent>" +
            "<xsd:extension base=\"xsd:string\"> \n" +
            "<xsd:attribute name=\"code\" type=\"xsd:positiveInteger\"/> \n" +
            "<xsd:attribute name=\"quantity\" type=\"xsd:positiveInteger\"/> \n" +
            "<xsd:attribute name=\"price\" type=\"xsd:decimal\"/> \n" +
            "</xsd:extension> \n" +
            "</xsd:simpleContent> \n" +
            "</xsd:complexType> \n" +
            "</xsd:element> \n" +
            "</xsd:sequence> \n" + //"<!-- Attribute Of Aisle --> \n" +
            "<xsd:attribute name=\"name\" type=\"xsd:string\"/> \n" +
            "<xsd:attribute name=\"number\" type=\"xsd:positiveInteger\"/> \n" + //"<!-- Of Aisle --> \n" +
            "</xsd:complexType> \n" +
            "<xsd:keyref name=\"NoIllegalEntries\" refer=\"itemKey\"> \n" +
            "<xsd:selector xpath=\"item\"/> \n" +
            "<xsd:field xpath=\"@code\"/> \n" +
            "</xsd:keyref> \n" +
            "</xsd:element> \n" +
            "<xsd:element name=\"items\"> \n" +
            "<xsd:complexType> \n" +
            "<xsd:sequence> \n" +
            "<xsd:element name=\"item\" maxOccurs=\"unbounded\"> \n" +
            "<xsd:complexType> \n" +
            "<xsd:simpleContent> \n" +
            "<xsd:extension base=\"xsd:string\"> \n" +
            "<xsd:attribute name=\"code\" type=\"xsd:positiveInteger\"/> \n" +
            "</xsd:extension> \n" +
            "</xsd:simpleContent> \n" +
            "</xsd:complexType> \n" +
            "</xsd:element> \n" +
            "</xsd:sequence> \n" +
            "</xsd:complexType> \n" +
            "</xsd:element> \n" +
            "</xsd:sequence> \n" +
            "<xsd:attribute name=\"name\" type=\"xsd:string\"/> \n" +
            "</xsd:complexType> \n" +
            "<xsd:key name=\"itemKey\"> \n" +
            "<xsd:selector xpath=\"items/item\"/> \n" +
            "<xsd:field xpath=\"@code\"/> \n" +
            "</xsd:key> \n" +
            "</xsd:element> \n" +
            "</xsd:schema>";


        String keyRefInstance =
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?> \n" +
            "<supermarket xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"C:\\tmp\\Supermarket.xsd\" name=\"String\"> \n" +
            "<aisle name=\"String\" number=\"2\"> \n" +
            "<item code=\"1234\" quantity=\"2\" price=\"3.1415926535897932384626433832795\">String</item> \n" +
            "</aisle> \n" +
            "<items> \n" +
            "<item code=\"1234\">Java</item> \n" +
            "</items> \n" +
            "</supermarket>";

        validateInstance(new String[]{keyrefXSD}, new String[]{keyRefInstance}, null);
    }


    /**
     * Loads the class at runtime and inspects for appropriate methods
     * Statically using methods (class.getGeneration()) would stop build
     * if the bug resurfaced.
     * <p/>
     * [XMLBEANS-45]   <xsd:redefine> tag is not supported
     */
    @Disabled
    public void test_jira_XmlBeans45() throws Exception {
        //this class is built during the build.schemas target
        Class<?> cls = Class.forName("xmlbeans45.PersonName");
        //check for methods in class
        //getGeneration()
        if (cls.getMethod("getGeneration") == null) {
            throw new Exception("getGeneration() was not found in class");
        }
        //getTitle()
        if (cls.getMethod("getTitle") == null) {
            throw new Exception("getTitle() was not found in class");
        }
        //getForenameArray()
        if (cls.getMethod("getForenameArray") == null) {
            throw new Exception("getForenameArray() was not found in class");
        }

    }

    /**
     * Could not Repro this
     * [XMLBEANS-46] Regex validation fails in multi-threaded, multi-processor environment
     */
    @Test
    void test_jira_XmlBeans46() throws Exception {
        RegexThread[] threads = new RegexThread[45];

        for (int i = 0; i < threads.length; i++) {
            threads[i] = new RegexThread();
            System.out.println("Thread[" + i + "]-starting ");
            threads[i].start();
        }

        Thread.sleep(6000);
        System.out.println("Done with RegEx Threading Test...");

        StringBuilder sb = new StringBuilder();
        for (RegexThread thread : threads) {
            if (thread.getException() != null) {
                sb.append(thread.getException().getMessage() + "\n");
            }
        }

        if (sb.length() > 0) {
            throw new Exception("Threaded Regex Validation Failed\n" + sb.toString());
        }
    }


    /**
     * Incorrect XML
     * [XMLBEANS-48]   Bug with Root.fetch ( Splay parent, QName name, QNameSet set, int n )
     */
    @Test
    void test_jira_XmlBeans48() throws Exception {
        String incorrectXml = "<sch:Feed xmlns:sch=\"http://xmlbeans_48\">" +
                              "<sch:Feed>" +
                              "<sch:Location>http://xmlbeans.apache.org</sch:Location>" +
                              "<sch:TimeEntered>2004-08-11T15:50:23.064-04:00</sch:TimeEntered>" +
                              "</sch:Feed>" +
                              "</sch:Feed>";

        xmlbeans48.FeedDocument feedDoc = (xmlbeans48.FeedDocument) XmlObject.Factory.parse(incorrectXml);
        FeedInfoType feedInfoType = feedDoc.getFeed();
        String location = feedInfoType.getLocation();
        System.out.println("Location: " + location);
        if (location != null) {
            throw new Exception("Location value should not have been populated");
        }

        String correctXml = "<sch:Feed xmlns:sch=\"http://xmlbeans_48\">" +
                            "<sch:Location>http://xmlbeans.apache.org</sch:Location>" +
                            "<sch:TimeEntered>2004-08-11T15:50:23.064-04:00</sch:TimeEntered>" +
                            "</sch:Feed>";

        feedDoc = (xmlbeans48.FeedDocument) XmlObject.Factory.parse(correctXml);
        feedInfoType = feedDoc.getFeed();
        location = feedInfoType.getLocation();
        System.out.println("Location: " + location);
        if (location == null) {
            throw new Exception("Location value should have been populated");
        }
    }

    /*
     * [XMLBEANS-49]: Schema compiler won't compile portlet.xsd from jsr168/pluto
     */
    @Test
    void test_jira_xmlbeans49() {
        List<XmlError> errors = new ArrayList<>();
        Parameters params = new Parameters();
        params.setXsdFiles(new File(scompTestFilesRoot + "xmlbeans_49.xsd_"));
        params.setErrorListener(errors);
        params.setSrcDir(schemaCompSrcDir);
        params.setClassesDir(schemaCompClassesDir);

        // needs network downloads enabled
        params.setDownload(true);

        SchemaCompiler.compile(params);

        // view errors
        assertFalse(hasSevereError(errors));
    }

    /**
     * For Testing jira issue 46
     */
    public static class RegexThread extends TestThread {
        Random rand;

        public RegexThread() {
            super();
            xmlbeans46.UsPhoneNumberDocument phone = xmlbeans46.UsPhoneNumberDocument.Factory.newInstance();
            rand = new Random();
        }

        /**
         * Validates a type that uses the following pattern
         * <xs:restriction base="xs:string">
         * <xs:pattern value="\d{3}\-\d{3}\-\d{4}"/>
         * </xs:restriction>
         */
        public void run() {
            try {

                for (int i = 0; i < 9; i++) {
                    int pre = rand.nextInt(999);
                    int mid = rand.nextInt(999);
                    int post = rand.nextInt(9999);
                    String testVal = ((pre > 100) ? String.valueOf(pre) : "128") + "-" +
                                     ((mid > 100) ? String.valueOf(mid) : "256") + "-" +
                                     ((post > 1000) ? String.valueOf(post) : "1024");

                    String xmlData = "<xb:usPhoneNumber xmlns:xb=\"http://xmlbeans_46\">" +
                                     testVal +
                                     "</xb:usPhoneNumber>";
                    //cannot repro using this method
                    //phone.setUsPhoneNumber(testVal);
                    //if (!phone.validate(xm)) {
                    //    _throwable = new Throwable("Multi Threaded Regular " +
                    //            "Expression did not validate - " + testVal);
                    //    if (errors != null && errors.size() > 0)
                    //        System.err.println("ERROR: " + errors);
                    //}

                    boolean validated = parseAndValidate(xmlData);
                    if (!validated) {
                        System.out.println("Not Valid!!!");
                    }
                    System.out.println("Validated " + testVal + " successfully ");
                }
                _result = true;

            } catch (Throwable t) {
                _throwable = t;
                t.printStackTrace();
            }
        }

        private boolean parseAndValidate(String val) throws XmlException {
            xmlbeans46.UsPhoneNumberDocument xml = xmlbeans46.UsPhoneNumberDocument.Factory.parse(val);
            return validate(xml);
        }

        private boolean validate(xmlbeans46.UsPhoneNumberDocument rdd) {
            List<XmlError> errors = new ArrayList<>();
            XmlOptions validateOptions = new XmlOptions();
            validateOptions.setErrorListener(errors);
            boolean valid = rdd.validate(validateOptions);
            if (!valid) {
                for (XmlError xmlError : errors) {
                    System.out.println("XML Error - " + xmlError.getMessage() + " at\n" + xmlError.getCursorLocation().xmlText());
                }

            }
            return valid;
        }
    }
}
