/*   Copyright 2006 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.XmlCursor;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.junit.jupiter.api.Test;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import static common.Common.P;
import static common.Common.XBEAN_CASE_ROOT;
import static org.junit.jupiter.api.Assertions.*;
import static xmlcursor.common.BasicCursorTestCase.cur;

/** This class tests the use of XmlOptions in binding XQuery variables */
public class XQueryVariableBindingTest
{
    private static final String XQUERY_CASE_DIR = XBEAN_CASE_ROOT + P + "xmlcursor" + P + "xquery";
    private static final File DIR = new File(XQUERY_CASE_DIR);
    private static final String XML =
        "<elem1>" +
        "<elem11 id=\"123\">text11</elem11>" +
        "<elem21 id=\"456\">text11</elem21>" +
        "<elem12 idRef=\"123\"/>" +
        "<elem13 idRef=\"456\"/>" +
        "<elem14 idRef=\"123\"/>" +
        "<elem15 idRef=\"456\"/>" +
        "<elem16 idRef=\"123\"/>" +
        "<elem17 idRef=\"789\"/>" +
        "</elem1>";

    private void _verifySelection(XmlCursor xc) {
        assertEquals(3, xc.getSelectionCount());
        assertTrue(xc.toNextSelection());
        assertEquals("<elem12 idRef=\"123\"/>", xc.xmlText());
        assertTrue(xc.toNextSelection());
        assertEquals("<elem14 idRef=\"123\"/>", xc.xmlText());
        assertTrue(xc.toNextSelection());
        assertEquals("<elem16 idRef=\"123\"/>", xc.xmlText());
    }

    /** test the automatic binding of $this to the current node: selectPath() */
    @Test
    void testThisVariable1() throws Exception {
        try (XmlCursor xc = cur(XML)) {
            xc.toFirstChild(); //<elem1>
            xc.toFirstChild(); //<elem11>
            xc.selectPath("//*[@idRef=$this/@id]");
            _verifySelection(xc);
            xc.clearSelections();
        }
    }

    // this fails: see JIRA issue XMLBEANS-276
    /** test the binding of a variable to the current node: selectPath() */
    @Test
    void testCurrentNodeVariable1() throws Exception {
        try (XmlCursor xc = cur(XML)) {
            xc.toFirstChild();
            xc.toFirstChild();
            XmlOptions opts = new XmlOptions();
            opts.setXqueryCurrentNodeVar("cur");
            //String varDecl = "declare variable $cur external; ";
            //xc.selectPath(varDecl + "//*[@idRef=$cur/@id]", opts);
            xc.selectPath("//*[@idRef=$cur/@id]", opts);
            _verifySelection(xc);
            xc.clearSelections();
        }
    }

    private XmlCursor _testDocCursor2() throws Exception {
        File f = new File(DIR, "employees.xml");
        XmlObject doc = XmlObject.Factory.parse(f);
        return doc.newCursor();
    }

    public void _verifyQueryResult(XmlCursor qc) {
        System.out.println(qc.xmlText());
        assertTrue(qc.toFirstChild());
        assertEquals("<phone location=\"work\">(425)555-5665</phone>", qc.xmlText());
        assertTrue(qc.toNextSibling());
        assertEquals("<phone location=\"work\">(425)555-6897</phone>", qc.xmlText());
        assertFalse(qc.toNextSibling());
    }

    /** test the automatic binding of $this to the current node: execQuery() */
    @Test
    void testThisVariable2() throws Exception
    {
        String q =
            "for $e in $this/employees/employee " +
            "let $s := $e/address/state " +
            "where $s = 'WA' " +
            "return $e//phone[@location='work']";
        try (XmlCursor xc = _testDocCursor2();
            XmlCursor qc = xc.execQuery(q)) {
            _verifyQueryResult(qc);
        }
    }

    /** test the binding of a variable to the current node: execQuery() */
    @Test
    void testCurrentNodeVariable2() throws Exception {
        String q =
            "for $e in $cur/employees/employee " +
            "let $s := $e/address/state " +
            "where $s = 'WA' " +
            "return $e//phone[@location='work']";
        XmlOptions opts = new XmlOptions();
        opts.setXqueryCurrentNodeVar("cur");
        try (XmlCursor xc = _testDocCursor2();
            XmlCursor qc = xc.execQuery(q, opts)) {
            _verifyQueryResult(qc);
        }
    }

    private XmlObject[] _execute(XmlObject xo, Map<String,Object> m, String q) {
        XmlOptions opts = new XmlOptions();
        opts.setXqueryVariables(m);
        return xo.execQuery(q, opts);
    }

    /** test the binding of a variable to an XmlTokenSource using a map */
    @Test
    void testOneVariable() throws Exception {
        File f = new File(DIR, "bookstore.xml");
        XmlObject doc = XmlObject.Factory.parse(f);
        String q =
            "declare variable $rt external; " +
            "for $x in $rt/book " +
            "where $x/price > 30 " +
            "return $x/title";
        Map<String,Object> m = new HashMap<>();
        m.put("rt", doc.selectChildren("", "bookstore")[0]);
        XmlObject[] results = _execute(doc, m, q);
        assertNotNull(results);
        assertEquals(2, results.length);
        assertEquals("<title lang=\"en\">XQuery Kick Start</title>", results[0].xmlText());
        assertEquals("<title lang=\"en\">Learning XML</title>", results[1].xmlText());
    }

    /** test the binding of multiple variables using a map;
        at the same time, test the binding of a variable to a String
     */
    @Test
    void testMultipleVariables() throws Exception {
        File f = new File(DIR, "bookstore.xml");
        XmlObject doc = XmlObject.Factory.parse(f);
        String q =
            "declare variable $rt external; " +
            "declare variable $c external; " +
            "for $x in $rt/book " +
            "where $x[@category=$c] " +
            "return $x/title";
        Map<String,Object> m = new HashMap<>();
        m.put("rt", doc.selectChildren("", "bookstore")[0]);
        m.put("c", "CHILDREN");
        XmlObject[] results = _execute(doc, m, q);
        assertNotNull(results);
        assertEquals(1, results.length);
        assertEquals("<title lang=\"en\">Harry Potter</title>", results[0].xmlText());
    }

}
