package com.altamiracorp.lumify.storm.textHighlighting;

import com.altamiracorp.lumify.core.model.artifactHighlighting.OffsetItem;
import com.altamiracorp.lumify.core.model.artifactHighlighting.TermMentionOffsetItem;
import com.altamiracorp.lumify.core.model.graph.GraphRepository;
import com.altamiracorp.lumify.core.model.graph.GraphVertex;
import com.altamiracorp.lumify.core.model.termMention.TermMentionModel;
import com.altamiracorp.lumify.core.user.User;
import com.google.inject.Inject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.PriorityQueue;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.json.JSONException;
import org.json.JSONObject;

public class EntityHighlighter {
    private final GraphRepository graphRepository;

    @Inject
    public EntityHighlighter(GraphRepository graphRepository) {
        this.graphRepository = graphRepository;
    }

    public String getHighlightedText(String text, Iterable<TermMentionModel> termMentions, User user) {
        List<OffsetItem> offsetItems = convertTermMentionsToOffsetItems(termMentions, user);
        return getHighlightedText(text, 0, offsetItems);
    }

    // TODO: change to use an InputStream?
    public static String getHighlightedText(String text, int textStartOffset, List<OffsetItem> offsetItems) throws JSONException {
        Collections.sort(offsetItems);
        StringBuilder result = new StringBuilder();
        PriorityQueue<Integer> endOffsets = new PriorityQueue<Integer>();
        int lastStart = textStartOffset;
        for (int i = 0; i < offsetItems.size(); i++) {
            OffsetItem offsetItem = offsetItems.get(i);

            boolean overlapsPreviousItem = false;
            if (offsetItem instanceof TermMentionOffsetItem) {
                for (int j = 0; j < i; j++) {
                    OffsetItem compareItem = offsetItems.get(j);
                    if (compareItem instanceof TermMentionOffsetItem && (compareItem.getEnd() >= offsetItem.getEnd()
                            || compareItem.getEnd() > offsetItem.getStart())) {
                        overlapsPreviousItem = true;
                        offsetItems.remove(i--);
                        break;
                    }
                }
            }
            if (overlapsPreviousItem) {
                continue;
            }
            if (offsetItem.getStart() < textStartOffset || offsetItem.getEnd() < textStartOffset) {
                continue;
            }
            if (!offsetItem.shouldHighlight()) {
                continue;
            }

            while (endOffsets.size() > 0 && endOffsets.peek() <= offsetItem.getStart()) {
                int end = endOffsets.poll();
                result.append(text.substring(lastStart - textStartOffset, end - textStartOffset));
                result.append("</span>");
                lastStart = end;
            }
            result.append(text.substring(lastStart - textStartOffset, (int) (offsetItem.getStart() - textStartOffset)));

            JSONObject infoJson = offsetItem.getInfoJson();

            result.append("<span");
            result.append(" class=\"");
            result.append(StringUtils.join(offsetItem.getCssClasses(), " "));
            result.append("\"");
            if (offsetItem.getTitle() != null) {
                result.append(" title=\"");
                result.append(StringEscapeUtils.escapeHtml(offsetItem.getTitle()));
                result.append("\"");
            }
            result.append(" data-info=\"");
            result.append(StringEscapeUtils.escapeHtml(infoJson.toString()));
            result.append("\"");
            result.append(">");
            endOffsets.add((int) offsetItem.getEnd());
            lastStart = (int) offsetItem.getStart();
        }

        while (endOffsets.size() > 0) {
            int end = endOffsets.poll();
            result.append(text.substring(lastStart - textStartOffset, end - textStartOffset));
            result.append("</span>");
            lastStart = end;
        }
        result.append(text.substring(lastStart - textStartOffset));

        return result.toString();
    }

    public List<OffsetItem> convertTermMentionsToOffsetItems(Iterable<TermMentionModel> termMentions, User user) {
        ArrayList<OffsetItem> termMetadataOffsetItems = new ArrayList<OffsetItem>();
        for (TermMentionModel termMention : termMentions) {
            GraphVertex glyphVertex = null;
            String graphVertexId = termMention.getMetadata().getGraphVertexId();
            if (graphVertexId != null) {
                glyphVertex = graphRepository.findVertex(graphVertexId, user);
            }
            termMetadataOffsetItems.add(new TermMentionOffsetItem(termMention, glyphVertex));
        }
        return termMetadataOffsetItems;
    }
}

@@ -257,29 +257,36 @@
 del.
-graph.GraphRepository
+termMention.TermMentionModel
 ;%0Aim
@@ -323,31 +323,17 @@
 ore.
-model.graph.GraphVertex
+user.User
 ;%0Aim
@@ -358,54 +358,25 @@
 orp.
-lumify.core.model.termMention.TermMentionModel
+securegraph.Graph
 ;%0Aim
@@ -397,37 +397,34 @@
 iracorp.
-lumify.core.user.User
+securegraph.Vertex
 ;%0Aimport
@@ -454,121 +454,8 @@
 ct;%0A
-import java.util.ArrayList;%0Aimport java.util.Collections;%0Aimport java.util.List;%0Aimport java.util.PriorityQueue;%0A
 impo
@@ -604,16 +604,130 @@
 bject;%0A%0A
+import java.util.ArrayList;%0Aimport java.util.Collections;%0Aimport java.util.List;%0Aimport java.util.PriorityQueue;%0A%0A
 public c
@@ -778,34 +778,14 @@
 raph
-Repository graphRepository
+ graph
 ;%0A%0A 
@@ -833,84 +833,44 @@
 raph
-Repository graphRepository) %7B%0A        this.graphRepository = graphRepository
+ graph) %7B%0A        this.graph = graph
 ;%0A  
@@ -4407,21 +4407,16 @@
         
-Graph
 Vertex g
@@ -4595,23 +4595,12 @@
 raph
-Repository.find
+.get
 Vert
@@ -4617,24 +4617,44 @@
 rtexId, user
+.getAuthorizations()
 );%0A         

fix entity highlighter