/**
 * 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;
  }
}

/**
 * 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) {
      CharSequence text = mLayout.getText();
      if (text instanceof Spanned) {
        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 spanned = (Spanned) text;
            RCTRawText[] link = spanned.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;
  }
}

Fix Nodes crash when text is not spanned