/*
 * Copyright (C) Telly, Inc. and other contributors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.telly.mrvector;

import android.annotation.TargetApi;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.util.Log;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import static android.graphics.PorterDuff.Mode;
import static android.graphics.PorterDuff.Mode.SRC_IN;
import static android.os.Build.VERSION.SDK_INT;
import static android.os.Build.VERSION_CODES.LOLLIPOP;
import static android.util.LayoutDirection.LTR;
import static com.telly.mrvector.VectorDrawable.LOGTAG;

/**
 * @hide
 */
public class Utils {
  /**
   * Stolen from Drawable
   */
  static final Mode DEFAULT_TINT_MODE = SRC_IN;
  static final boolean LOLLIPOP_PLUS = SDK_INT >= LOLLIPOP;

  static Map<String, Method> sCachedMethods = new HashMap<>();
  static Class[][] sCachedArgsTypes = {
    {int.class}, {PorterDuff.Mode.class}, {}
  };

  @SuppressWarnings("unchecked")
  public static <T> T tryInvoke(Object target, String methodName, Class<?>[] argTypes,
                         Object... args) {

    try {
      Method method = sCachedMethods.get(methodName);
      if(method != null){
          return (T) method.invoke(target, args);
      }

      method = target.getClass().getDeclaredMethod(methodName, argTypes);
      sCachedMethods.put(methodName, method);

      return (T) method.invoke(target, args);
    } catch (Exception pokemon) {
      Log.e(LOGTAG, "Unable to invoke " + methodName + " on " + target, pokemon);
    }

    return null;
  }

  static int getLayoutDirection(Drawable drawable) {
    final Integer layoutDirection = tryInvoke(drawable, "getLayoutDirection", sCachedArgsTypes[2]);
    return layoutDirection == null ? LTR : layoutDirection.intValue();
  }

  /**
   * Parses a {@link Mode} from a tintMode
   * attribute's enum value.
   *
   * @hide
   */
  static Mode parseTintMode(int value, Mode defaultMode) {
    switch (value) {
      case 3: return Mode.SRC_OVER;
      case 5: return Mode.SRC_IN;
      case 9: return Mode.SRC_ATOP;
      case 14: return Mode.MULTIPLY;
      case 15: return Mode.SCREEN;

      case 16:
          if(Build.VERSION.SDK_INT > 11) {
              return Mode.ADD;
          }

      default:
          return defaultMode;
    }
  }

  /**
   * Ensures the tint filter is consistent with the current tint color and
   * mode.
   */
  static PorterDuffColorFilter updateTintFilter(Drawable drawable, PorterDuffColorFilter tintFilter, ColorStateList tint,
                                                PorterDuff.Mode tintMode) {
    if (tint == null || tintMode == null) {
      return null;
    }

    final int color = tint.getColorForState(drawable.getState(), Color.TRANSPARENT);

    if (tintFilter == null || !LOLLIPOP_PLUS) { // TODO worth caching them?
      return new PorterDuffColorFilter(color, tintMode);
    }

    tryInvoke(tintFilter, "setColor", sCachedArgsTypes[0], color);
    tryInvoke(tintFilter, "setMode", sCachedArgsTypes[1],tintMode);
    return tintFilter;
  }

  @TargetApi(LOLLIPOP)
  static int getChangingConfigurations(TypedArray a) {
    if (LOLLIPOP_PLUS) {
      return a.getChangingConfigurations();
    }
    return 0;
  }
}

@@ -972,40 +972,27 @@
 .v4.
-graphics.drawable.DrawableCompat
+util.SimpleArrayMap
 ;%0Aim
@@ -1052,33 +1052,8 @@
 od;%0A
-import java.util.Arrays;%0A
 impo
@@ -1248,16 +1248,72 @@
 DK_INT;%0A
+import static android.os.Build.VERSION_CODES.HONEYCOMB;%0A
 import s
@@ -1648,17 +1648,16 @@
 LLIPOP;%0A
-%0A
   static
@@ -1657,16 +1657,90 @@
  static 
+final boolean HONEYCOMB_PLUS = SDK_INT %3E= HONEYCOMB;%0A%0A  static SimpleArray
 Map%3CStri
@@ -1772,20 +1772,27 @@
 s = new 
-Hash
+SimpleArray
 Map%3C%3E();
@@ -1792,18 +1792,25 @@
 ap%3C%3E();%0A
+%0A
   
+final 
 static C
@@ -1819,79 +1819,116 @@
 ss%5B%5D
-%5B%5D sCachedArgsTypes = %7B%0A    %7Bint.class%7D, %7BPorterDuff.Mode.class%7D, %7B%7D%0A  
+ INT_ARG = %7Bint.class%7D;%0A  final static Class%5B%5D MODE_ARG = %7BMode.class%7D;%0A  final static Class%5B%5D EMPTY_ARG = %7B
 %7D;%0A%0A
@@ -2185,26 +2185,24 @@
 l)%7B%0A        
-  
 return (T) m
@@ -2685,27 +2685,17 @@
 n%22, 
-sCachedArgsTypes%5B2%5D
+EMPTY_ARG
 );%0A 
@@ -3155,47 +3155,29 @@
     
-  
 if(
-Build.VERSION.SDK_INT %3E 11) %7B%0A    
+HONEYCOMB_PLUS) %7B%0A
     
@@ -3203,26 +3203,24 @@
 DD;%0A        
-  
 %7D%0A%0A      def
@@ -3225,18 +3225,16 @@
 efault:%0A
-  
         
@@ -3898,27 +3898,15 @@
 r%22, 
-sCachedArgsTypes%5B0%5D
+INT_ARG
 , co
@@ -3952,28 +3952,18 @@
 e%22, 
-sCachedArgsTypes%5B1%5D,
+MODE_ARG, 
 tint

improve code quality