/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

package com.facebook.react.views.text;

import android.content.res.AssetManager;
import android.graphics.Paint;
import android.graphics.Typeface;

import androidx.annotation.Nullable;

import com.facebook.react.bridge.ReadableArray;

import java.util.ArrayList;
import java.util.List;

public class ReactTypefaceUtils {
  public static final int UNSET = -1;

  public static int parseFontWeight(@Nullable String fontWeightString) {
    int fontWeightNumeric =
        fontWeightString != null ? parseNumericFontWeight(fontWeightString) : UNSET;
    int fontWeight = fontWeightNumeric != UNSET ? fontWeightNumeric : Typeface.NORMAL;

    if (fontWeight == 700 || "bold".equals(fontWeightString)) fontWeight = Typeface.BOLD;
    else if (fontWeight == 400 || "normal".equals(fontWeightString)) fontWeight = Typeface.NORMAL;

    return fontWeight;
  }

  public static int parseFontStyle(@Nullable String fontStyleString) {
    int fontStyle = UNSET;
    if ("italic".equals(fontStyleString)) {
      fontStyle = Typeface.ITALIC;
    } else if ("normal".equals(fontStyleString)) {
      fontStyle = Typeface.NORMAL;
    }

    return fontStyle;
  }

  public static @Nullable String parseFontVariant(@Nullable ReadableArray fontVariantArray) {
    if (fontVariantArray == null || fontVariantArray.size() == 0) {
      return null;
    }

    List<String> features = new ArrayList<>();
    for (int i = 0; i < fontVariantArray.size(); i++) {
      // see https://docs.microsoft.com/en-us/typography/opentype/spec/featurelist
      switch (fontVariantArray.getString(i)) {
        case "small-caps":
          features.add("'smcp'");
          break;
        case "oldstyle-nums":
          features.add("'onum'");
          break;
        case "lining-nums":
          features.add("'lnum'");
          break;
        case "tabular-nums":
          features.add("'tnum'");
          break;
        case "proportional-nums":
          features.add("'pnum'");
          break;
      }
    }

    return String.join(", ", features);
  }

  public static Typeface applyStyles(@Nullable Typeface typeface,
                                         int style, int weight, @Nullable String family, AssetManager assetManager) {
    int oldStyle;
    if (typeface == null) {
      oldStyle = 0;
    } else {
      oldStyle = typeface.getStyle();
    }

    int want = 0;
    if ((weight == Typeface.BOLD)
        || ((oldStyle & Typeface.BOLD) != 0 && weight == ReactTextShadowNode.UNSET)) {
      want |= Typeface.BOLD;
    }

    if ((style == Typeface.ITALIC)
        || ((oldStyle & Typeface.ITALIC) != 0 && style == ReactTextShadowNode.UNSET)) {
      want |= Typeface.ITALIC;
    }

    if (family != null) {
      typeface = ReactFontManager.getInstance().getTypeface(family, want, weight, assetManager);
    } else if (typeface != null) {
      // TODO(t9055065): Fix custom fonts getting applied to text children with different style
      typeface = Typeface.create(typeface, want);
    }

    if (typeface != null) {
      return typeface;
    } else {
      return Typeface.defaultFromStyle(want);
    }
  }

  /**
   * Return -1 if the input string is not a valid numeric fontWeight (100, 200, ..., 900), otherwise
   * return the weight.
   */
  private static int parseNumericFontWeight(String fontWeightString) {
    // This should be much faster than using regex to verify input and Integer.parseInt
    return fontWeightString.length() == 3
        && fontWeightString.endsWith("00")
        && fontWeightString.charAt(0) <= '9'
        && fontWeightString.charAt(0) >= '1'
        ? 100 * (fontWeightString.charAt(0) - '0')
        : UNSET;
  }
}

@@ -291,13 +291,16 @@
 ics.
-Paint
+Typeface
 ;%0Aim
@@ -312,35 +312,31 @@
 android.
-graphics.Typeface;%0A
+text.TextUtils;
 %0Aimport 
@@ -365,17 +365,16 @@
 llable;%0A
-%0A
 import c
@@ -413,17 +413,16 @@
 eArray;%0A
-%0A
 import j
@@ -1711,16 +1711,29 @@
     
-switch (
+String fontVariant = 
 font
@@ -1757,20 +1757,84 @@
 tring(i)
-) %7B%0A
+;%0A      if (fontVariant != null) %7B%0A        switch (fontVariant) %7B%0A  
         
@@ -1848,24 +1848,26 @@
 mall-caps%22:%0A
+  
           fe
@@ -1890,32 +1890,34 @@
 p'%22);%0A          
+  
 break;%0A        c
@@ -1911,24 +1911,26 @@
 ak;%0A        
+ 
+ 
 case %22oldsty
@@ -1931,32 +1931,34 @@
 oldstyle-nums%22:%0A
+  
           featur
@@ -1977,32 +1977,34 @@
 m'%22);%0A          
+  
 break;%0A        c
@@ -1998,24 +1998,26 @@
 ak;%0A        
+ 
+ 
 case %22lining
@@ -2016,32 +2016,34 @@
  %22lining-nums%22:%0A
+  
           featur
@@ -2062,39 +2062,43 @@
 m'%22);%0A          
+  
 break;%0A
+  
         case %22ta
@@ -2112,32 +2112,34 @@
 ums%22:%0A          
+  
 features.add(%22't
@@ -2148,39 +2148,43 @@
 m'%22);%0A          
+  
 break;%0A
+  
         case %22pr
@@ -2203,32 +2203,34 @@
 ums%22:%0A          
+  
 features.add(%22'p
@@ -2243,31 +2243,43 @@
 ;%0A          
+  
 break;%0A
+        %7D%0A
       %7D%0A    
@@ -2292,22 +2292,25 @@
  return 
-String
+TextUtils
 .join(%22,
@@ -2366,16 +2366,23 @@
 yStyles(
+%0A      
 @Nullabl
@@ -2406,43 +2406,8 @@
 ce,%0A
-                                   
     
@@ -2418,16 +2418,22 @@
 t style,
+%0A     
  int wei
@@ -2436,16 +2436,22 @@
  weight,
+%0A     
  @Nullab
@@ -2467,16 +2467,22 @@
  family,
+%0A     
  AssetMa
@@ -3733,32 +3733,36 @@
 () == 3%0A        
+    
 && fontWeightStr
@@ -3780,32 +3780,36 @@
 h(%2200%22)%0A        
+  
+  
 && fontWeightStr
@@ -3829,16 +3829,20 @@
  %3C= '9'%0A
+    
         

Fix crash when using TextInput.FontVariant prop in Android API level < 26