package models.nodes;

import com.fasterxml.jackson.databind.JsonNode;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import managers.nodes.AVMManager;
import play.libs.F.Function;
import play.libs.F.Promise;


public class LHS extends AVM {

    public static final AVMManager nodes = new AVMManager();

    public Rule parent;

    public LHS(String uuid) {
        this.jsonProperties.put("uuid", uuid);
    }

    public LHS(Rule rule) {
        super(rule);
        this.parent = rule;
    }

    public Promise<UUID> getUUID() {
        Promise<UUID> parentUUID = this.parent.getUUID();
        return parentUUID.map(new UUIDFunction());
    }

    public Promise<List<Feature>> getAllFeatures() {
        Promise<JsonNode> json = this.toJSON();
        return json.map(
            new Function<JsonNode, List<Feature>>() {
                public List<Feature> apply(JsonNode json) {
                    List<Feature> features = new ArrayList<Feature>();
                    List<JsonNode> featureNodes = json
                        .findValues("attribute");
                    for (JsonNode featureNode : featureNodes) {
                        String name = featureNode.findValue("name").asText();
                        features.add(new Feature(name));
                    }
                    return features;
                }
            });
    }

    public Promise<LHS> get() {
        Promise<JsonNode> json = this.toJSON();
        final LHS lhs = this;
        return json.map(
            new Function<JsonNode, LHS>() {
                public LHS apply(JsonNode json) {
                    lhs.json = json;
                    return lhs;
                }
            });
    }

    public Promise<JsonNode> getValue(
        final Feature feature, final UUID uuid) {
        final LHS lhs = this;
        Promise<UUID> lhsUUID = this.getUUID();
        return lhsUUID.flatMap(
            new Function<UUID, Promise<JsonNode>>() {
                public Promise<JsonNode> apply(UUID lhsUUID) {
                    if (lhsUUID.equals(uuid)) {
                        lhs.jsonProperties.put("uuid", lhsUUID.toString());
                        return feature.getValue(lhs.rule, lhs);
                    }
                    Substructure substructure =
                        new Substructure(lhs.rule, uuid);
                    return feature.getValue(lhs.rule, substructure);
                }
            });
    }

    protected static class UUIDFunction implements Function<UUID, UUID> {
        public UUID apply(UUID parentUUID) {
            byte[] bytes = parentUUID.toString()
                .getBytes(Charset.forName("UTF-8"));
            return UUID.nameUUIDFromBytes(bytes);
        }
    }

}

@@ -1762,750 +1762,8 @@
  %7D%0A%0A
-    public Promise%3CJsonNode%3E getValue(%0A        final Feature feature, final UUID uuid) %7B%0A        final LHS lhs = this;%0A        Promise%3CUUID%3E lhsUUID = this.getUUID();%0A        return lhsUUID.flatMap(%0A            new Function%3CUUID, Promise%3CJsonNode%3E%3E() %7B%0A                public Promise%3CJsonNode%3E apply(UUID lhsUUID) %7B%0A                    if (lhsUUID.equals(uuid)) %7B%0A                        lhs.jsonProperties.put(%22uuid%22, lhsUUID.toString());%0A                        return feature.getValue(lhs.rule, lhs);%0A                    %7D%0A                    Substructure substructure =%0A                        new Substructure(lhs.rule, uuid);%0A                    return feature.getValue(lhs.rule, substructure);%0A                %7D%0A            %7D);%0A    %7D%0A%0A
     

Enable operations that write to the DB to be rolled back on error by wrapping them in transactions.