package org.commcare.suite.model;

import org.commcare.session.RemoteQuerySessionManager;
import org.javarosa.core.model.condition.EvaluationContext;
import org.javarosa.core.util.externalizable.DeserializationException;
import org.javarosa.core.util.externalizable.ExtUtil;
import org.javarosa.core.util.externalizable.ExtWrapList;
import org.javarosa.core.util.externalizable.ExtWrapNullable;
import org.javarosa.core.util.externalizable.ExtWrapTagged;
import org.javarosa.core.util.externalizable.Externalizable;
import org.javarosa.core.util.externalizable.PrototypeFactory;
import org.javarosa.xpath.expr.XPathExpression;

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

/**
 * An action defines a user interface element that can be
 * triggered by the user to fire off one or more stack operations
 * in the current session
 *
 * @author ctsims
 */
public class Action implements Externalizable {

    private DisplayUnit display;
    private Vector<StackOperation> stackOps;
    private XPathExpression relevantExpr;
    private String iconForActionBar;

    /**
     * Serialization only!!!
     */
    @SuppressWarnings("unused")
    public Action() {

    }

    /**
     * Creates an Action model with the associated display details and stack
     * operations set.
     */
    public Action(DisplayUnit display, Vector<StackOperation> stackOps,
                  XPathExpression relevantExpr, String iconForActionBar) {
        this.display = display;
        this.stackOps = stackOps;
        this.relevantExpr = relevantExpr;
        this.iconForActionBar = iconForActionBar == null ? "" : iconForActionBar;
    }

    /**
     * @return The Display model for showing this action to the user
     */
    public DisplayUnit getDisplay() {
        return display;
    }

    /**
     * @return A vector of the StackOperation models which
     * should be processed sequentially upon this action
     * being triggered by the user.
     */
    public Vector<StackOperation> getStackOperations() {
        return stackOps;
    }

    public boolean isRelevant(EvaluationContext evalContext) {
        if (relevantExpr == null) {
            return true;
        } else {
            String result = RemoteQuerySessionManager.evalXpathExpression(relevantExpr, evalContext);
            return "true".equals(result);
        }
    }

    public boolean hasActionBarIcon() {
        return !"".equals(iconForActionBar);
    }

    @Override
    public void readExternal(DataInputStream in, PrototypeFactory pf) throws IOException, DeserializationException {
        display = (DisplayUnit)ExtUtil.read(in, DisplayUnit.class, pf);
        stackOps = (Vector<StackOperation>)ExtUtil.read(in, new ExtWrapList(StackOperation.class), pf);
        relevantExpr = (XPathExpression)ExtUtil.read(in, new ExtWrapNullable(new ExtWrapTagged()), pf);
        iconForActionBar = ExtUtil.readString(in);
    }

    @Override
    public void writeExternal(DataOutputStream out) throws IOException {
        ExtUtil.write(out, display);
        ExtUtil.write(out, new ExtWrapList(stackOps));
        ExtUtil.write(out, new ExtWrapNullable(relevantExpr == null ? null : new ExtWrapTagged(relevantExpr)));
        ExtUtil.writeString(out, iconForActionBar);
    }
}

@@ -1123,18 +1123,27 @@
 ctionBar
+Reference
 ;%0A
-
 %0A    /**
@@ -1642,16 +1642,25 @@
 ctionBar
+Reference
  = iconF
@@ -2498,33 +2498,139 @@
 iconForActionBar
-)
+Reference);%0A    %7D%0A%0A    public String getActionBarIconReference() %7B%0A        return iconForActionBarReference
 ;%0A    %7D%0A%0A    @Ov
@@ -3057,16 +3057,25 @@
 ctionBar
+Reference
  = ExtUt
@@ -3387,24 +3387,24 @@
 antExpr)));%0A
-
         ExtU
@@ -3440,16 +3440,25 @@
 ctionBar
+Reference
 );%0A    %7D

rename field