/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

package com.facebook.react.flat;

import javax.annotation.Nullable;

import android.text.Layout;
import android.text.Spanned;

/* package */ final class TextNodeRegion extends NodeRegion {
  private @Nullable Layout mLayout;

  /* package */ TextNodeRegion(
      float left,
      float top,
      float right,
      float bottom,
      int tag,
      boolean isVirtual,
      @Nullable Layout layout) {
    super(left, top, right, bottom, tag, isVirtual);
    mLayout = layout;
  }

  public void setLayout(Layout layout) {
    mLayout = layout;
  }

  /* package */ @Nullable Layout getLayout() {
    return mLayout;
  }

  /* package */ int getReactTag(float touchX, float touchY) {
    if (mLayout != null) {
      int y = Math.round(touchY - mTop);
      if (y >= mLayout.getLineTop(0) && y < mLayout.getLineBottom(mLayout.getLineCount() - 1)) {
        float x = Math.round(touchX - mLeft);
        int line = mLayout.getLineForVertical(y);

        if (mLayout.getLineLeft(line) <= x && x <= mLayout.getLineRight(line)) {
          int off = mLayout.getOffsetForHorizontal(line, x);

          Spanned text = (Spanned) mLayout.getText();
          RCTRawText[] link = text.getSpans(off, off, RCTRawText.class);

          if (link.length != 0) {
            return link[0].getReactTag();
          }
        }
      }
    }

    return super.getReactTag(touchX, touchY);
  }

  @Override
  boolean matchesTag(int tag) {
    if (super.matchesTag(tag)) {
      return true;
    }

    if (mLayout != null) {
      Spanned text = (Spanned) mLayout.getText();
      RCTRawText[] spans = text.getSpans(0, text.length(), RCTRawText.class);
      for (RCTRawText span : spans) {
        if (span.getReactTag() == tag) {
          return true;
        }
      }
    }
    return false;
  }
}

@@ -1013,24 +1013,108 @@
  != null) %7B%0A
+      CharSequence text = mLayout.getText();%0A      if (text instanceof Spanned) %7B%0A  
       int y 
@@ -1144,24 +1144,26 @@
 Top);%0A      
+  
 if (y %3E= mLa
@@ -1245,24 +1245,26 @@
 ) %7B%0A        
+  
 float x = Ma
@@ -1293,24 +1293,26 @@
 t);%0A        
+ 
+ 
 int line = m
@@ -1338,24 +1338,26 @@
 rtical(y);%0A%0A
+  
         if (
@@ -1431,24 +1431,26 @@
 %7B%0A          
+ 
+ 
 int off = mL
@@ -1495,32 +1495,34 @@
 %0A%0A          
+  
 Spanned 
 text = (Span
@@ -1501,36 +1501,39 @@
         Spanned 
-text
+spanned
  = (Spanned) mLa
@@ -1529,35 +1529,24 @@
 panned) 
-mLayout.getText();%0A
+text;%0A  
         
@@ -1567,20 +1567,23 @@
  link = 
-text
+spanned
 .getSpan
@@ -1620,24 +1620,26 @@
 %0A%0A          
+  
 if (link.len
@@ -1646,24 +1646,26 @@
 gth != 0) %7B%0A
+  
             
@@ -1690,24 +1690,38 @@
 ReactTag();%0A
+            %7D%0A
           %7D%0A

Fix Nodes crash when text is not spanned