package org.commcare.cases.entity;

import org.commcare.cases.util.StringUtils;
import org.commcare.modern.util.Pair;
import org.javarosa.core.model.instance.TreeReference;

import java.util.*;


/**
 * Filter entity list via all string-representable entity fields
 */
public class EntityStringFilterer {
    private final boolean isFilterEmpty;
    private final String[] searchTerms;
    private final ArrayList<Pair<Integer, Integer>> matchScores = new ArrayList<>();
    private final boolean isAsyncMode;
    private final boolean isFuzzySearchEnabled;

    private final NodeEntityFactory nodeFactory;
    //private final EntityListAdapter adapter;
    protected final List<Entity<TreeReference>> matchList;
    protected final List<Entity<TreeReference>> fullEntityList;


    public EntityStringFilterer(String[] searchTerms,
                                boolean isAsyncMode, boolean isFuzzySearchEnabled,
                                NodeEntityFactory nodeFactory,
                                List<Entity<TreeReference>> fullEntityList) {
        this.matchList = new ArrayList<>();
        this.nodeFactory = nodeFactory;
        this.fullEntityList = fullEntityList;
        this.isAsyncMode = isAsyncMode;
        this.isFuzzySearchEnabled = isFuzzySearchEnabled;
        this.isFilterEmpty = searchTerms == null || searchTerms.length == 0;
        this.searchTerms = searchTerms;
        if (isFilterEmpty) {
            matchList.addAll(fullEntityList);
        }
    }

    public List<Entity<TreeReference>> buildMatchList() {

        while (!nodeFactory.isEntitySetReady()) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        Locale currentLocale = Locale.getDefault();
        //It's a bit sketchy here, because this DB lock will prevent
        //anything else from processing
        for (int index = 0; index < fullEntityList.size(); ++index) {
            Entity<TreeReference> e = fullEntityList.get(index);
            boolean add = false;
            int score = 0;
            filter:
            for (String filter : searchTerms) {
                add = false;
                for (int i = 0; i < e.getNumFields(); ++i) {
                    String field = e.getNormalizedField(i).toLowerCase();
                    if (!"".equals(field) && field.toLowerCase(currentLocale).contains(filter.toLowerCase())) {
                        add = true;
                        continue filter;
                    } else if (isFuzzySearchEnabled) {
                        // We possibly now want to test for edit distance for
                        // fuzzy matching
                        for (String fieldChunk : e.getSortFieldPieces(i)) {
                            Pair<Boolean, Integer> match = StringUtils.fuzzyMatch(filter, fieldChunk);
                            if (match.first) {
                                add = true;
                                score += match.second;
                                continue filter;
                            }
                        }
                    }
                }
                if (!add) {
                    break;
                }
            }
            if (add) {
                matchScores.add(Pair.create(index, score));
            }
        }
        if (isAsyncMode) {
            Collections.sort(matchScores, new Comparator<Pair<Integer, Integer>>() {
                @Override
                public int compare(Pair<Integer, Integer> lhs, Pair<Integer, Integer> rhs) {
                    return lhs.second - rhs.second;
                }
            });
        }

        for (Pair<Integer, Integer> match : matchScores) {
            matchList.add(fullEntityList.get(match.first));
        }
        return matchList;
    }
}

@@ -33,52 +33,8 @@
 y;%0A%0A
-import org.commcare.cases.util.StringUtils;%0A
 impo
@@ -140,17 +140,109 @@
 va.util.
-*
+ArrayList;%0Aimport java.util.List;%0Aimport java.util.Locale;%0Aimport java.util.stream.Collectors
 ;%0A%0A%0A/**%0A
@@ -350,49 +350,8 @@
 r %7B%0A
-    private final boolean isFilterEmpty;%0A
     
@@ -474,95 +474,8 @@
 %3E();
-%0A    private final boolean isAsyncMode;%0A    private final boolean isFuzzySearchEnabled;
 %0A%0A  
@@ -525,55 +525,8 @@
 ry;%0A
-    //private final EntityListAdapter adapter;%0A
     
@@ -704,91 +704,8 @@
 ms,%0A
-                                boolean isAsyncMode, boolean isFuzzySearchEnabled,%0A
     
@@ -988,235 +988,93 @@
 his.
-isAsyncMode = isAsyncMode;%0A        this.isFuzzySearchEnabled = isFuzzySearchEnabled;%0A        this.isFilterEmpty = searchTerms == null %7C%7C searchTerms.length == 0;%0A        this.searchTerms = searchTerms;%0A        if (isFilterEmpty
+searchTerms = searchTerms;%0A        if (searchTerms == null %7C%7C searchTerms.length == 0
 ) %7B%0A
@@ -1463,117 +1463,8 @@
 ();%0A
-        //It's a bit sketchy here, because this DB lock will prevent%0A        //anything else from processing%0A
     
@@ -2100,1239 +2100,208 @@
    %7D
- else if (isFuzzySearchEnabled) %7B%0A                        // We possibly now want to test for edit distance for%0A                        // fuzzy matching%0A                        for (String fieldChunk : e.getSortFieldPieces(i)) %7B%0A                            Pair%3CBoolean, Integer%3E match = StringUtils.fuzzyMatch(filter, fieldChunk);%0A                            if (match.first) %7B%0A                                add = true;%0A                                score += match.second;%0A                                continue filter;%0A                            %7D%0A                        %7D%0A                    %7D%0A                %7D%0A                if (!add) %7B%0A                    break;%0A                %7D%0A            %7D%0A            if (add) %7B%0A                matchScores.add(Pair.create(index, score));%0A            %7D%0A        %7D%0A        if (isAsyncMode) %7B%0A            Collections.sort(matchScores, new Comparator%3CPair%3CInteger, Integer%3E%3E() %7B%0A                @Override%0A                public int compare(Pair%3CInteger, Integer%3E lhs, Pair%3CInteger, Integer%3E rhs) %7B%0A                    return lhs.second - rhs.second;%0A                %7D%0A            %7D);%0A        %7D%0A%0A        for (Pair%3CInteger, Integer%3E match : matchScores) %7B%0A            matchList.add(
+%0A                %7D%0A            %7D%0A            if (add) %7B%0A                matchScores.add(Pair.create(index, score));%0A            %7D%0A        %7D%0A%0A        matchList.addAll(matchScores.stream().map(match -%3E 
 full
@@ -2328,27 +2328,47 @@
 .first))
-;%0A        %7D
+.collect(Collectors.toList()));
 %0A       

Update EntityStringFilterer to remove unused variables/patterns from Anroid