content: /*
   * Copyright (C) 2016 Bilibili
   *
   * 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.bilibili.magicasakura.utils;
  
  import android.content.Context;
  import android.content.res.ColorStateList;
  import android.content.res.Resources;
  import android.content.res.TypedArray;
  import android.content.res.XmlResourceParser;
  import android.graphics.Color;
  import android.graphics.ColorFilter;
  import android.graphics.PorterDuff;
  import android.graphics.PorterDuffColorFilter;
  import android.graphics.drawable.ColorDrawable;
  import android.graphics.drawable.Drawable;
  import android.os.Build;
  import android.util.AttributeSet;
  import android.util.StateSet;
  import android.util.TypedValue;
  import android.util.Xml;
  
  import com.wm.remusic.R;
  
  import org.xmlpull.v1.XmlPullParser;
  import org.xmlpull.v1.XmlPullParserException;
  
  import java.io.IOException;
  
  /**
   * @author xyczero617@gmail.com
   * @time 16/2/22
   */
  public abstract class DrawableUtils {
  
      protected abstract Drawable inflateDrawable(Context context, XmlPullParser parser, AttributeSet attrs) throws IOException, XmlPullParserException;
  
      static Drawable createDrawable(Context context, int resId) {
          if (resId <= 0) return null;
  
          final TypedValue typedValue = new TypedValue();
          final Resources res = context.getResources();
          res.getValue(resId, typedValue, true);
          Drawable dr = null;
  
          if (typedValue.type >= TypedValue.TYPE_FIRST_COLOR_INT
                  && typedValue.type <= TypedValue.TYPE_LAST_COLOR_INT) {
              dr = new ColorDrawable(ThemeUtils.replaceColorById(context, resId));
          } else {
              try {
                  if (typedValue.string != null && typedValue.string.toString().endsWith("xml")) {
                      final XmlResourceParser rp = res.getXml(resId);
                      final AttributeSet attrs = Xml.asAttributeSet(rp);
                      int type;
  
                      while ((type = rp.next()) != XmlPullParser.START_TAG &&
                              type != XmlPullParser.END_DOCUMENT) {
                          // Empty loop
                      }
                      if (type != XmlPullParser.START_TAG) {
                          throw new XmlPullParserException("No start tag found");
                      }
  
                      dr = createFromXmlInner(context, rp, attrs);
                      rp.close();
                  }
              } catch (IOException e) {
                  e.printStackTrace();
              } catch (XmlPullParserException e) {
                  e.printStackTrace();
              }
          }
          return dr;
      }
  
      static Drawable createFromXmlInner(Context context, XmlPullParser parser, AttributeSet attrs) throws IOException, XmlPullParserException {
          final DrawableUtils drawableUtils;
  
          final String name = parser.getName();
          switch (name) {
              case "selector":
                  drawableUtils = new StateListDrawableUtils();
                  break;
              case "shape":
                  drawableUtils = new GradientDrawableUtils();
                  break;
              case "layer-list":
                  drawableUtils = new LayerDrawableUtils();
                  break;
              default:
                  drawableUtils = null;
          }
          return drawableUtils == null ? null : drawableUtils.inflateDrawable(context, parser, attrs);
      }
  
      /**
       * Extracts state_ attributes from an attribute set.
       *
       * @param attrs The attribute set.
       * @return An array of state_ attributes.
       */
      protected int[] extractStateSet(AttributeSet attrs) {
          int j = 0;
          final int numAttrs = attrs.getAttributeCount();
          int[] states = new int[numAttrs];
          for (int i = 0; i < numAttrs; i++) {
              final int stateResId = attrs.getAttributeNameResource(i);
              if (stateResId == 0) {
                  break;
              } else if (stateResId == android.R.attr.drawable
                      || stateResId == android.R.attr.id
                      || stateResId == R.attr.drawableTint
                      || stateResId == R.attr.drawableTintMode) {
                  // Ignore attributes from StateListDrawableItem and
                  // AnimatedStateListDrawableItem.
                  continue;
              } else {
                  states[j++] = attrs.getAttributeBooleanValue(i, false)
                          ? stateResId : -stateResId;
              }
          }
          states = StateSet.trimStateSet(states, j);
          return states;
      }
  
      static int getAttrTintColor(Context context, AttributeSet attrs, int attr, int defaultValue) {
          final TypedArray a = obtainAttributes(context.getResources(), context.getTheme(), attrs, new int[]{attr});
          final int tintColor = ThemeUtils.replaceColor(context, a.getColor(0, defaultValue));
          a.recycle();
          return tintColor;
      }
  
      static Drawable getAttrDrawable(Context context, AttributeSet attrs, int attr) {
          final TypedArray a = obtainAttributes(context.getResources(), context.getTheme(), attrs, new int[]{attr});
          final int resId = a.getResourceId(0, 0);
          Drawable drawable = null;
          if (resId != 0) {
              drawable = createDrawable(context, resId);
              if (drawable == null) {
                  drawable = a.getDrawable(0);
              }
          }
          a.recycle();
          return drawable;
      }
  
      static ColorFilter getAttrColorFilter(Context context, AttributeSet attrs, int tintAttr, int tintModeAttr) {
          final int color = getAttrColor(context, attrs, tintAttr, Color.TRANSPARENT);
          if (color == Color.TRANSPARENT) return null;
          return new PorterDuffColorFilter(color, getTintMode(context, attrs, tintModeAttr));
      }
  
      static ColorStateList getTintColorList(Context context, AttributeSet attrs, int tintAttr) {
          TypedArray a = obtainAttributes(context.getResources(), context.getTheme(), attrs, new int[]{tintAttr});
          if (!a.hasValue(0)) {
              a.recycle();
              return null;
          }
          final ColorStateList cls = TintManager.get(context).getColorStateList(a.getResourceId(0, 0));
          a.recycle();
          return cls;
      }
  
      static PorterDuff.Mode getTintMode(Context context, AttributeSet attrs, int tintModeAttr) {
          TypedArray a = obtainAttributes(context.getResources(), context.getTheme(), attrs, new int[]{tintModeAttr});
          final int tintModeValue = a.getInt(0, 0);
          a.recycle();
          return parseTintMode(tintModeValue, PorterDuff.Mode.SRC_IN);
      }
  
      static int getAttrDimensionPixelSize(Context context, AttributeSet attrs, int attr) {
          return getAttrDimensionPixelSize(context, attrs, attr, 0);
      }
  
      static int getAttrDimensionPixelSize(Context context, AttributeSet attrs, int attr, int defaultValue) {
          TypedArray a = obtainAttributes(context.getResources(), context.getTheme(), attrs, new int[]{attr});
          final int value = a.getDimensionPixelSize(0, defaultValue);
          a.recycle();
          return value;
      }
  
      static int getAttrColor(Context context, AttributeSet attrs, int attr, int defaultValue) {
          TypedArray a = obtainAttributes(context.getResources(), context.getTheme(), attrs, new int[]{attr});
          final int colorId = a.getResourceId(0, 0);
          final int value = colorId != 0 ? ThemeUtils.replaceColorById(context, colorId) : ThemeUtils.replaceColor(context, a.getColor(0, defaultValue));
          a.recycle();
          return value;
      }
  
      static int getAttrDimensionPixelOffset(Context context, AttributeSet attrs, int attr) {
          return getAttrDimensionPixelOffset(context, attrs, attr, 0);
      }
  
      static int getAttrDimensionPixelOffset(Context context, AttributeSet attrs, int attr, int defaultValue) {
          TypedArray a = obtainAttributes(context.getResources(), context.getTheme(), attrs, new int[]{attr});
          final int value = a.getDimensionPixelOffset(0, defaultValue);
          a.recycle();
          return value;
      }
  
      static float getAttrDimension(Context context, AttributeSet attrs, int attr) {
          return getAttrDimension(context, attrs, attr, 0);
      }
  
      static float getAttrDimension(Context context, AttributeSet attrs, int attr, int defaultValue) {
          TypedArray a = obtainAttributes(context.getResources(), context.getTheme(), attrs, new int[]{attr});
          final float value = a.getDimension(0, defaultValue);
          a.recycle();
          return value;
      }
  
      static float getAttrFloat(Context context, AttributeSet attrs, int attr, float defaultValue) {
          TypedArray a = obtainAttributes(context.getResources(), context.getTheme(), attrs, new int[]{attr});
          final float alphaMod = a.getFloat(0, defaultValue);
          a.recycle();
          return alphaMod;
      }
  
      static int getAttrInt(Context context, AttributeSet attrs, int attr, int defaultValue) {
          TypedArray a = obtainAttributes(context.getResources(), context.getTheme(), attrs, new int[]{attr});
          final int value = a.getInt(0, defaultValue);
          a.recycle();
          return value;
      }
  
      static boolean getAttrBoolean(Context context, AttributeSet attrs, int attr, boolean defaultValue) {
          TypedArray a = obtainAttributes(context.getResources(), context.getTheme(), attrs, new int[]{attr});
          final boolean value = a.getBoolean(0, defaultValue);
          a.recycle();
          return value;
      }
  
      static boolean getAttrHasValue(Context context, AttributeSet attrs, int attr) {
          TypedArray a = obtainAttributes(context.getResources(), context.getTheme(), attrs, new int[]{attr});
          final boolean flag = a.hasValue(0);
          a.recycle();
          return flag;
      }
  
      static int getAttrResourceId(Context context, AttributeSet attrs, int attr, int defaultValue) {
          TypedArray a = obtainAttributes(context.getResources(), context.getTheme(), attrs, new int[]{attr});
          final int id = a.getResourceId(0, defaultValue);
          a.recycle();
          return id;
      }
  
      static TypedArray obtainAttributes(
              Resources res, Resources.Theme theme, AttributeSet set, int[] attrs) {
          if (theme == null) {
              return res.obtainAttributes(set, attrs);
          }
          return theme.obtainStyledAttributes(set, attrs, 0, 0);
      }
  
      public static PorterDuff.Mode parseTintMode(int value, PorterDuff.Mode defaultMode) {
          switch (value) {
              case 3:
                  return PorterDuff.Mode.SRC_OVER;
              case 5:
                  return PorterDuff.Mode.SRC_IN;
              case 9:
                  return PorterDuff.Mode.SRC_ATOP;
              case 14:
                  return PorterDuff.Mode.MULTIPLY;
              case 15:
                  return PorterDuff.Mode.SCREEN;
              case 16:
                  return Build.VERSION.SDK_INT >= 11 ? PorterDuff.Mode.valueOf("ADD")
                          : defaultMode;
              default:
                  return defaultMode;
          }
      }
  }
  