/*   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 xmlcursor.xquery.detailed;

import org.apache.xmlbeans.*;
import org.junit.Ignore;
import org.junit.Test;
import test.xbean.xmlcursor.xQueryInput.EmpT;
import tools.util.JarUtil;

import java.io.IOException;
import java.io.InputStream;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

public class XQueryTest {
    @Test
    @Ignore("XQuery on Cursor is invalid")
    public void testSimple() throws XmlException, IOException {
        String xq = "for $e in //employee where $e/name='Bob' return  $e ";
        String xq1 = "for $e in //employee return  $e ";
        InputStream input = JarUtil.getResourceFromJarasStream("xbean/xmlcursor/XQueryInput.xml");

        XmlObject o = XmlObject.Factory.parse(input);
        XmlCursor c = o.newCursor();
        XmlCursor c1 = c.execQuery(xq);
        c1.toFirstContentToken();
        assertEquals("<employee>\n" +
                     "\t\t<name>Bob</name>\n" +
                     "\t\t<ssn>1000</ssn>\n" +
                     "\t</employee>", c1.xmlText());

        XmlObject[] res = o.execQuery(xq);
        EmpT employeeType = (EmpT) res[0];
        assertEquals("Bob", employeeType.getName());
    }

    @Test
    public void testObjConstruction() throws XmlException, IOException {
        String query = JarUtil.getResourceFromJar("xbean/xmlcursor/xquery/Constructor.xq");
        InputStream input = JarUtil.getResourceFromJarasStream("xbean/xmlcursor/XQueryInput.xml");
        XmlObject o = XmlObject.Factory.parse(input);
        //via Object
        XmlObject[] reslt = o.execQuery(query);
        assertEquals(3, reslt.length);
        assertEquals("<person><name>Bob</name></person>",
            reslt[0].xmlText());
        assertEquals("<person><name>Beth</name></person>",
            reslt[1].xmlText());
        assertEquals("<person><name>NotBob</name></person>",
            reslt[2].xmlText());
        XmlCursor c = o.newCursor();

        //via Cursor
        /*XmlCursor c1=c.execQuery(query);
         c1.toFirstContentToken();
        assertEquals("<person><name>Bob</name></person>",
                      c1.xmlText() );
          c1.toNextSibling();
        assertEquals("<person><name>Beth</name></person>",
                      c1.xmlText() );
        c1.dispose();
        c.dispose();
        */
        int i = 0;
        while (i++ < 2) {
            //via Cursor--new
            XmlCursor c1 = c.execQuery(query);
            //c.dispose();
            assertEquals(XmlCursor.TokenType.STARTDOC, c1.currentTokenType());
            assertEquals(XmlCursor.TokenType.START, c1.toNextToken());
            assertEquals("<person><name>Bob</name></person>",
                c1.xmlText());
            // assertTrue(c1.toNextSelection());
            assertTrue(c1.toNextSibling());
            assertEquals("<person><name>Beth</name></person>",
                c1.xmlText());
            //assertTrue(c1.toNextSelection());
            assertTrue(c1.toNextSibling());
            assertEquals("<person><name>NotBob</name></person>",
                c1.xmlText());
            c1.dispose();
        }
        c.dispose();
    }

    @Test
    public void testJoin() throws XmlException, IOException {
        String query = JarUtil.getResourceFromJar("xbean/xmlcursor/xquery/Join.xq");
        InputStream input = JarUtil.getResourceFromJarasStream("xbean/xmlcursor/XQueryInput.xml");
        XmlObject o = XmlObject.Factory.parse(input);
        XmlCursor c = o.newCursor();
        XmlCursor c1 = c.execQuery(query);

        //  assertEquals(3, c1.getSelectionCount());
        c1.toFirstContentToken();
        assertEquals("<result>" +
                     "<ssn>1000</ssn>,\n" +
                     "\t\t<name>Bob</name>,\n" +
                     "\t\t<name>NotBob</name>" +
                     "</result>",
            c1.xmlText());
/*      assertEquals("<xml-fragment>" +
              "<result>" +
              "<ssn>1000</ssn>,\n" +
              "\t\t<name>Bob</name>,\n" +
              "\t\t<name>NotBob</name>" +
              "</result>" +
              "<result><ssn>1001</ssn>,\n" +
              "\t\t<name>Beth</name>,\n" +
              "\t\t</result>" +
              "<result><ssn>1000</ssn>,\n" +
              "\t\t<name>NotBob</name>,\n" +
              "\t\t<name>Bob</name>" +
              "</result>" +
              "</xml-fragment>",
                    c1.xmlText() ); */
        c1.dispose();
        c.dispose();

        XmlObject[] res = o.execQuery(query);
        assertEquals(3, res.length);
    }

    @Test
    public void testTextSequenceRootObject() throws XmlException, IOException {
        //String query = "$this//text()";
        String query = ".//text()";
        InputStream input = JarUtil.getResourceFromJarasStream("xbean/xmlcursor/XQueryInput.xml");
        XmlObject o = XmlObject.Factory.parse(input);
        XmlObject[] res = o.execQuery(query);
        assertEquals(19, res.length);
        input.close();
    }

    @Test
    @Ignore("Cursor support for //text() is invalid")
    public void testTextSequenceRootCursor() throws XmlException, IOException {
        String query = ".//text()";
        InputStream input = JarUtil.getResourceFromJarasStream("xbean/xmlcursor/XQueryInput.xml");
        XmlObject o = XmlObject.Factory.parse(input);
        XmlCursor c = o.newCursor();
        XmlCursor c1 = c.execQuery(query);
           assertEquals(XmlCursor.TokenType.TEXT,c1.toNextToken());
        //  assertEquals()
        //assertEquals(19, c1.getSelectionCount());
        c.dispose();//make sure this doesn't screw things up
        while (c1.toNextSibling())
            assertEquals(XmlCursor.TokenType.TEXT, c1.currentTokenType());
        c1.toStartDoc();
        assertEquals("<xml-fragment>Bob</xml-fragment>",
                c1.xmlText());
        c1.dispose();
        c.dispose();
    }

    @Test
    @Ignore("still bugged")
    public void testDocumentFunc() throws XmlException, IOException {
        //String query = "<result>{$this},{count(//employee)}</result>";
        String query = "<result>{.},{count(//employee)}</result>";
        InputStream input = JarUtil.getResourceFromJarasStream("xbean/xmlcursor/XQueryInput.xml");
        XmlCursor c = XmlObject.Factory.parse(input).newCursor();
        XmlCursor c1 = c.execQuery(query);
        assertEquals("",
            c1.xmlText());
        c1.dispose();
        c.dispose();
    }

    @Test
    public void testTextAtOddPlaces() throws Exception {
        //String query = "<result>{$this},{count(//employee)}</result>";
        String query = "<result>{.},{count(//employee)}</result>";
        String input = "<foo><a><b>text</b>more text</a></foo>";
        XmlObject o = XmlObject.Factory.parse(input);
        XmlCursor c = o.newCursor();

        XmlObject[] res = o.execQuery("//a");
        assertEquals("<a><b>text</b>more text</a>", res[0].xmlText());

        XmlCursor cur = c.execQuery("//a");
        // assertEquals(1, cur.getSelectionCount());
        cur.toFirstContentToken();
        assertEquals("<a><b>text</b>more text</a>", cur.xmlText());
    }

    @Test
    @Ignore
    public void testMultiDocJoin() throws XmlException, IOException {
        String query = JarUtil.getResourceFromJar("xbean/xmlcursor/xquery/2DocJoin.xq");
        InputStream input = JarUtil.getResourceFromJarasStream("xbean/xmlcursor/XQueryInput.xml");
        XmlCursor c = XmlObject.Factory.parse(input).newCursor();
        XmlCursor c1 = c.execQuery(query);
        assertEquals("",
            c1.xmlText());
        c1.dispose();
        c.dispose();
    }

    @Test
    public void testFunction() throws Exception {
        String query =
            " declare function local:summary($emps as element(employee)*) \n" +
            "   as element(dept)*\n" +
            "{\n" +
            "   for $d in fn:distinct-values($emps/deptno)\n" +
            "   let $e := $emps[deptno = $d]\n" +
            "   return\n" +
            "      <dept>\n" +
            "         <deptno>{$d}</deptno>\n" +
            "         <headcount> {fn:count($e)} </headcount>\n" +
            "         <payroll> {fn:sum($e/salary)} </payroll>\n" +
            "      </dept>\n" +
            "};\n" +
            "\n" +
            //"local:summary($this//employee[location = \"Denver\"])";
            "local:summary(.//employee[location = \"Denver\"])";

        String xml =
            " <list>" +
            "<employee>" +
            "<location>Denver</location>" +
            "<deptno>7</deptno>" +
            "<salary>20</salary>" +
            "</employee>" +
            "<employee>" +
            "<location>Seattle</location>" +
            "<deptno>6</deptno>" +
            "<salary>30</salary>" +
            "</employee>" +
            "<employee>" +
            "<location>Denver</location>" +
            "<deptno>5</deptno>" +
            "<salary>40</salary>" +
            "</employee>" +
            "<employee>" +
            "<location>Denver</location>" +
            "<deptno>7</deptno>" +
            "<salary>10</salary>" +
            "</employee>" +
            "</list>";

        XmlObject o = XmlObject.Factory.parse(xml);
        XmlObject[] res = o.execQuery(query);
        assertEquals(2, res.length);
        assertEquals("<dept><deptno>7</deptno><headcount>2</headcount><payroll>30</payroll></dept>",
            res[0].xmlText());
        assertEquals("<dept><deptno>5</deptno><headcount>1</headcount><payroll>40</payroll></dept>",
            res[1].xmlText());
        XmlCursor c = o.newCursor();
        XmlCursor c1 = c.execQuery(query);
        c1.toFirstContentToken();
        assertEquals(res[0].xmlText(),
            c1.xmlText());
        c1.dispose();
        c.dispose();
    }

    @Test
    public void testType() throws Exception {
        String xml = "<a><b></b><b></b></a>";
        String query = "count(//b)";
        XmlObject o = XmlObject.Factory.parse(xml);
        XmlObject[] res = o.execQuery(query);
        XmlLong result = (XmlLong) res[0];
        assertEquals("2", result.getStringValue());
        assertEquals(2, result.getLongValue());
    }

    @Test
    public void testQueryComment() throws Exception {
        String xml = "<a><b></b><b></b></a>";
        String query = "(:comment:) count(//b)";
        XmlObject o = XmlObject.Factory.parse(xml);
        XmlObject[] res = o.execQuery(query);
        XmlLong result = (XmlLong) res[0];
        assertEquals("2", result.getStringValue());
        assertEquals(2, result.getLongValue());
    }

    @Test
    @Ignore
    public void testStandaloneFunction() throws Exception {
        String query =
            "<results>\n" +
            "       {fn:not(xs:unsignedShort(\"65535\"))}\n" +
            "      </results>";
        XmlObject o = XmlObject.Factory.newInstance();
        XmlObject[] res = o.execQuery(query);
        XmlLong result = (XmlLong) res[0];
        assertEquals("2", result.getStringValue());
        assertEquals(2, result.getLongValue());
    }
}
