package com.vanniktech.emoji;

import android.content.Context;
import android.text.Spannable;
import com.vanniktech.emoji.emoji.Emoji;

final class EmojiHandler {
  static void addEmojis(final Context context, final Spannable text, final int emojiSize) {
    final EmojiSpan[] spans = text.getSpans(0, text.length(), EmojiSpan.class);

    for (final EmojiSpan oldSpan : spans) {
      text.removeSpan(oldSpan);
    }

    int i = 0;

    final EmojiManager instance = EmojiManager.getInstance();

    while (i < text.length()) {
      final Emoji found = instance.findEmoji(text.subSequence(i, text.length()));

      if (found != null) {
        text.setSpan(new EmojiSpan(context, found.getResource(), emojiSize), i, i + found.getLength(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
        i += found.getLength();
      } else {
        i++;
      }
    }
  }

  private EmojiHandler() {
    throw new AssertionError("No instances.");
  }
}

@@ -127,16 +127,146 @@
 i.Emoji;
+%0Aimport java.util.ArrayList;%0Aimport java.util.List;%0A%0Aimport static com.vanniktech.emoji.EmojiHandler.SpanRangeList.SPAN_NOT_FOUND;
 %0A%0Afinal 
@@ -392,88 +392,72 @@
 nal 
-EmojiSpan%5B%5D spans = text.getSpans(0, text.length(), EmojiSpan.class
+SpanRangeList existingSpanRanges = new SpanRangeList(text
 );%0A
-%0A
     
-for (
 fina
@@ -467,164 +467,372 @@
 moji
-Span oldSpan : spans) %7B%0A      text.removeSpan(oldSpan);%0A    %7D%0A%0A    int i = 0;%0A%0A
+Manager emojiManager = EmojiManager.getInstance();%0A    int index = 0;%0A%0A    while (index %3C text.length()) %7B%0A      final int existingSpanEnd = existingSpanRanges.spanEnd(index);%0A%0A      if (existingSpanEnd == SPAN_NOT_FOUND) %7B%0A 
     
+   
 final 
-EmojiManager instance = EmojiManager.getInstance();%0A%0A    while (i %3C
+int nextSpanStart = existingSpanRanges.nextSpanStart(index);%0A        final int searchRange = nextSpanStart == SPAN_NOT_FOUND ?
  tex
@@ -833,36 +833,52 @@
  ? text.length()
-) %7B%0A
+ : nextSpanStart;%0A  
       final Emoj
@@ -887,24 +887,28 @@
 found = 
-instance
+emojiManager
 .findEmo
@@ -932,28 +932,32 @@
 ce(i
-, text.length()
+ndex, searchRange
 ));%0A%0A
+  
     
@@ -975,24 +975,26 @@
  != null) %7B%0A
+  
         text
@@ -1059,19 +1059,27 @@
 Size), i
-, i
+ndex, index
  + found
@@ -1091,16 +1091,34 @@
 ength(),
+%0A                 
  Spannab
@@ -1129,10 +1129,10 @@
 PAN_
-IN
+EX
 CLUS
@@ -1147,16 +1147,19 @@
 USIVE);%0A
+%0A  
         
@@ -1159,16 +1159,20 @@
        i
+ndex
  += foun
@@ -1192,16 +1192,18 @@
 ;%0A      
+  
 %7D else %7B
@@ -1203,16 +1203,18 @@
  else %7B%0A
+  
         
@@ -1218,12 +1218,83 @@
    i
+ndex
 ++;%0A
+        %7D%0A      %7D else %7B%0A        index += existingSpanEnd - index;%0A
     
@@ -1385,11 +1385,986 @@
 .%22);%0A  %7D
+%0A%0A  static final class SpanRangeList %7B%0A    static final int SPAN_NOT_FOUND = -1;%0A%0A    private final List%3CRange%3E spanRanges = new ArrayList%3C%3E();%0A%0A    SpanRangeList(final Spannable text) %7B%0A      for (final EmojiSpan span : text.getSpans(0, text.length(), EmojiSpan.class)) %7B%0A        spanRanges.add(new Range(text.getSpanStart(span), text.getSpanEnd(span)));%0A      %7D%0A    %7D%0A%0A    int spanEnd(final int index) %7B%0A      for (final Range spanRange : spanRanges) %7B%0A        if (spanRange.start == index) %7B%0A          return spanRange.end;%0A        %7D%0A      %7D%0A%0A      return SPAN_NOT_FOUND;%0A    %7D%0A%0A    int nextSpanStart(final int index) %7B%0A      for (final Range spanRange : spanRanges) %7B%0A        if (spanRange.start %3E index) %7B%0A          return spanRange.start;%0A        %7D%0A      %7D%0A%0A      return SPAN_NOT_FOUND;%0A    %7D%0A  %7D%0A%0A  static final class Range %7B%0A    final int start;%0A    final int end;%0A%0A    Range(final int start, final int end) %7B%0A      this.start = start;%0A      this.end = end;%0A    %7D%0A  %7D
 %0A%7D%0A

Make the EmojiEditText and EmojiTextView more performant (#93)