package org.commcare.suite.model;

import org.commcare.util.DatumUtil;
import org.javarosa.core.model.condition.EvaluationContext;
import org.javarosa.core.model.instance.TreeReference;
import org.javarosa.core.util.externalizable.DeserializationException;
import org.javarosa.core.util.externalizable.ExtUtil;
import org.javarosa.core.util.externalizable.ExtWrapTagged;
import org.javarosa.core.util.externalizable.PrototypeFactory;
import org.javarosa.xpath.expr.XPathExpression;
import org.javarosa.xpath.expr.XPathPathExpr;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

/**
 * Data class for single value query data elements
 *
 * ```
 * <data key="case_id_list">
 *   <list nodeset="instance('selected_cases')/session-data"
 *         exclude="count(instance('casedb')/casedb/case[@case_id = current()/value] = 1)"
 *         ref="value"/>
 * </data>
 * ```
 */
public class ListQueryData implements QueryData {
    private String key;
    private TreeReference nodeset;
    private XPathExpression excludeExpr;
    private XPathPathExpr ref;

    @SuppressWarnings("unused")
    public ListQueryData() {}

    public ListQueryData(String key, TreeReference nodeset, XPathExpression excludeExpr, XPathPathExpr ref) {
        this.key = key;
        this.nodeset = nodeset;
        this.excludeExpr = excludeExpr;
        this.ref = ref;
    }

    @Override
    public String getKey() {
        return key;
    }

    @Override
    public Iterable<String> getValues(EvaluationContext ec) {
        List<String> values = new ArrayList<String>();

        Vector<TreeReference> result = ec.expandReference(nodeset);

        for (TreeReference node : result) {
            EvaluationContext temp = new EvaluationContext(ec, node);
            if (!(boolean) excludeExpr.eval(temp)) {
                values.add(DatumUtil.getReturnValueFromSelection(node, ref, ec));
            }
        }
        return values;
    }

    @Override
    public void readExternal(DataInputStream in, PrototypeFactory pf)
            throws IOException, DeserializationException {
        key = ExtUtil.readString(in);
        nodeset = (TreeReference)ExtUtil.read(in, TreeReference.class, pf);
        excludeExpr = (XPathExpression) ExtUtil.read(in, new ExtWrapTagged(), pf);
        ref = (XPathPathExpr) ExtUtil.read(in, new ExtWrapTagged(), pf);
    }

    @Override
    public void writeExternal(DataOutputStream out) throws IOException {
        ExtUtil.writeString(out, key);
        ExtUtil.write(out, nodeset);
        ExtUtil.write(out, new ExtWrapTagged(excludeExpr));
        ExtUtil.write(out, new ExtWrapTagged(ref));
    }
}

@@ -718,20 +718,12 @@
 for 
-single value
+list
  que
@@ -816,17 +816,17 @@
 selected
-_
+-
 cases')/
@@ -837,16 +837,22 @@
 ion-data
+/value
 %22%0A *    
@@ -927,19 +927,15 @@
 t()/
-value%5D
+.%5D)
  = 1
-)
 %22%0A *
@@ -948,21 +948,17 @@
    ref=%22
-value
+.
 %22/%3E%0A * %3C

comment update