package com.ypsx.base.util;

import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.InsetDrawable;
import android.view.View;

import androidx.annotation.ColorInt;
import androidx.annotation.IntDef;
import androidx.databinding.BindingAdapter;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;


import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.PARAMETER;

/**
 * 作者　: hegaojian
 * 时间　: 2020/4/10
 * 描述　:使用DataBinding时可以使用该库 https://github.com/whataa/noDrawable
 * 只需要复制核心类 ProxyDrawable，Drawables至项目中即可
 * 可以减少大量的drawable.xml文件
 */

public class Drawables {
    private static final String TAG = "Drawables";

    private static final int INVALID = 0;
    private static final int[] tmpPadding = new int[4];

    // normal, checked, checkable, enabled, focused, pressed, selected
    @BindingAdapter(value = {
            "drawable_shapeMode",
            "drawable_solidColor",
            "drawable_strokeColor",
            "drawable_strokeWidth",
            "drawable_strokeDash",
            "drawable_strokeDashGap",
            "drawable_radius",
            "drawable_radiusLT",
            "drawable_radiusLB",
            "drawable_radiusRT",
            "drawable_radiusRB",
            "drawable_startColor",
            "drawable_centerColor",
            "drawable_endColor",
            "drawable_orientation",
            "drawable_gradientType",
            "drawable_radialCenterX",
            "drawable_radialCenterY",
            "drawable_radialRadius",
            "drawable_width",
            "drawable_height",
            "drawable_marginLeft",
            "drawable_marginTop",
            "drawable_marginRight",
            "drawable_marginBottom",
            "drawable_ringThickness",
            "drawable_ringThicknessRatio",
            "drawable_ringInnerRadius",
            "drawable_ringInnerRadiusRatio",

            "drawable_checked_shapeMode",
            "drawable_checked_solidColor",
            "drawable_checked_strokeColor",
            "drawable_checked_strokeWidth",
            "drawable_checked_strokeDash",
            "drawable_checked_strokeDashGap",
            "drawable_checked_radius",
            "drawable_checked_radiusLT",
            "drawable_checked_radiusLB",
            "drawable_checked_radiusRT",
            "drawable_checked_radiusRB",
            "drawable_checked_startColor",
            "drawable_checked_centerColor",
            "drawable_checked_endColor",
            "drawable_checked_orientation",
            "drawable_checked_gradientType",
            "drawable_checked_radialCenterX",
            "drawable_checked_radialCenterY",
            "drawable_checked_radialRadius",
            "drawable_checked_width",
            "drawable_checked_height",
            "drawable_checked_marginLeft",
            "drawable_checked_marginTop",
            "drawable_checked_marginRight",
            "drawable_checked_marginBottom",
            "drawable_checked_ringThickness",
            "drawable_checked_ringThicknessRatio",
            "drawable_checked_ringInnerRadius",
            "drawable_checked_ringInnerRadiusRatio",

            "drawable_checkable_shapeMode",
            "drawable_checkable_solidColor",
            "drawable_checkable_strokeColor",
            "drawable_checkable_strokeWidth",
            "drawable_checkable_strokeDash",
            "drawable_checkable_strokeDashGap",
            "drawable_checkable_radius",
            "drawable_checkable_radiusLT",
            "drawable_checkable_radiusLB",
            "drawable_checkable_radiusRT",
            "drawable_checkable_radiusRB",
            "drawable_checkable_startColor",
            "drawable_checkable_centerColor",
            "drawable_checkable_endColor",
            "drawable_checkable_orientation",
            "drawable_checkable_gradientType",
            "drawable_checkable_radialCenterX",
            "drawable_checkable_radialCenterY",
            "drawable_checkable_radialRadius",
            "drawable_checkable_width",
            "drawable_checkable_height",
            "drawable_checkable_marginLeft",
            "drawable_checkable_marginTop",
            "drawable_checkable_marginRight",
            "drawable_checkable_marginBottom",
            "drawable_checkable_ringThickness",
            "drawable_checkable_ringThicknessRatio",
            "drawable_checkable_ringInnerRadius",
            "drawable_checkable_ringInnerRadiusRatio",

            "drawable_enabled_shapeMode",
            "drawable_enabled_solidColor",
            "drawable_enabled_strokeColor",
            "drawable_enabled_strokeWidth",
            "drawable_enabled_strokeDash",
            "drawable_enabled_strokeDashGap",
            "drawable_enabled_radius",
            "drawable_enabled_radiusLT",
            "drawable_enabled_radiusLB",
            "drawable_enabled_radiusRT",
            "drawable_enabled_radiusRB",
            "drawable_enabled_startColor",
            "drawable_enabled_centerColor",
            "drawable_enabled_endColor",
            "drawable_enabled_orientation",
            "drawable_enabled_gradientType",
            "drawable_enabled_radialCenterX",
            "drawable_enabled_radialCenterY",
            "drawable_enabled_radialRadius",
            "drawable_enabled_width",
            "drawable_enabled_height",
            "drawable_enabled_marginLeft",
            "drawable_enabled_marginTop",
            "drawable_enabled_marginRight",
            "drawable_enabled_marginBottom",
            "drawable_enabled_ringThickness",
            "drawable_enabled_ringThicknessRatio",
            "drawable_enabled_ringInnerRadius",
            "drawable_enabled_ringInnerRadiusRatio",

            "drawable_focused_shapeMode",
            "drawable_focused_solidColor",
            "drawable_focused_strokeColor",
            "drawable_focused_strokeWidth",
            "drawable_focused_strokeDash",
            "drawable_focused_strokeDashGap",
            "drawable_focused_radius",
            "drawable_focused_radiusLT",
            "drawable_focused_radiusLB",
            "drawable_focused_radiusRT",
            "drawable_focused_radiusRB",
            "drawable_focused_startColor",
            "drawable_focused_centerColor",
            "drawable_focused_endColor",
            "drawable_focused_orientation",
            "drawable_focused_gradientType",
            "drawable_focused_radialCenterX",
            "drawable_focused_radialCenterY",
            "drawable_focused_radialRadius",
            "drawable_focused_width",
            "drawable_focused_height",
            "drawable_focused_marginLeft",
            "drawable_focused_marginTop",
            "drawable_focused_marginRight",
            "drawable_focused_marginBottom",
            "drawable_focused_ringThickness",
            "drawable_focused_ringThicknessRatio",
            "drawable_focused_ringInnerRadius",
            "drawable_focused_ringInnerRadiusRatio",

            "drawable_pressed_shapeMode",
            "drawable_pressed_solidColor",
            "drawable_pressed_strokeColor",
            "drawable_pressed_strokeWidth",
            "drawable_pressed_strokeDash",
            "drawable_pressed_strokeDashGap",
            "drawable_pressed_radius",
            "drawable_pressed_radiusLT",
            "drawable_pressed_radiusLB",
            "drawable_pressed_radiusRT",
            "drawable_pressed_radiusRB",
            "drawable_pressed_startColor",
            "drawable_pressed_centerColor",
            "drawable_pressed_endColor",
            "drawable_pressed_orientation",
            "drawable_pressed_gradientType",
            "drawable_pressed_radialCenterX",
            "drawable_pressed_radialCenterY",
            "drawable_pressed_radialRadius",
            "drawable_pressed_width",
            "drawable_pressed_height",
            "drawable_pressed_marginLeft",
            "drawable_pressed_marginTop",
            "drawable_pressed_marginRight",
            "drawable_pressed_marginBottom",
            "drawable_pressed_ringThickness",
            "drawable_pressed_ringThicknessRatio",
            "drawable_pressed_ringInnerRadius",
            "drawable_pressed_ringInnerRadiusRatio",

            "drawable_selected_shapeMode",
            "drawable_selected_solidColor",
            "drawable_selected_strokeColor",
            "drawable_selected_strokeWidth",
            "drawable_selected_strokeDash",
            "drawable_selected_strokeDashGap",
            "drawable_selected_radius",
            "drawable_selected_radiusLT",
            "drawable_selected_radiusLB",
            "drawable_selected_radiusRT",
            "drawable_selected_radiusRB",
            "drawable_selected_startColor",
            "drawable_selected_centerColor",
            "drawable_selected_endColor",
            "drawable_selected_orientation",
            "drawable_selected_gradientType",
            "drawable_selected_radialCenterX",
            "drawable_selected_radialCenterY",
            "drawable_selected_radialRadius",
            "drawable_selected_width",
            "drawable_selected_height",
            "drawable_selected_marginLeft",
            "drawable_selected_marginTop",
            "drawable_selected_marginRight",
            "drawable_selected_marginBottom",
            "drawable_selected_ringThickness",
            "drawable_selected_ringThicknessRatio",
            "drawable_selected_ringInnerRadius",
            "drawable_selected_ringInnerRadiusRatio",

            // normal, checked, checkable, enabled, focused, pressed, selected

            "drawable",
            "drawable_checked",
            "drawable_checkable",
            "drawable_enabled",
            "drawable_focused",
            "drawable_pressed",
            "drawable_selected",

    }, requireAll = false)
    public static void setViewBackground(
            View view,

            @ShapeMode int shapeMode,
            @ColorInt Integer solidColor,
            @ColorInt int strokeColor,
            float strokeWidth,
            float strokeDash,
            float strokeDashGap,
            float radius,
            float radiusLT,
            float radiusLB,
            float radiusRT,
            float radiusRB,
            @ColorInt Integer startColor,
            @ColorInt Integer centerColor,
            @ColorInt Integer endColor,
            @Orientation int orientation,
            @GradientType int gradientType,
            Float radialCenterX,
            Float radialCenterY,
            float radialRadius,
            float width,
            float height,
            float marginLeft,
            float marginTop,
            float marginRight,
            float marginBottom,
            float ringThickness,
            float ringThicknessRatio,
            float ringInnerRadius,
            float ringInnerRadiusRatio,

            @ShapeMode int checked_shapeMode,
            @ColorInt Integer checked_solidColor,
            @ColorInt int checked_strokeColor,
            float checked_strokeWidth,
            float checked_strokeDash,
            float checked_strokeDashGap,
            float checked_radius,
            float checked_radiusLT,
            float checked_radiusLB,
            float checked_radiusRT,
            float checked_radiusRB,
            @ColorInt Integer checked_startColor,
            @ColorInt Integer checked_centerColor,
            @ColorInt Integer checked_endColor,
            @Orientation int checked_orientation,
            @GradientType int checked_gradientType,
            Float checked_radialCenterX,
            Float checked_radialCenterY,
            float checked_radialRadius,
            float checked_width,
            float checked_height,
            float checked_marginLeft,
            float checked_marginTop,
            float checked_marginRight,
            float checked_marginBottom,
            float checked_ringThickness,
            float checked_ringThicknessRatio,
            float checked_ringInnerRadius,
            float checked_ringInnerRadiusRatio,

            @ShapeMode int checkable_shapeMode,
            @ColorInt Integer checkable_solidColor,
            @ColorInt int checkable_strokeColor,
            float checkable_strokeWidth,
            float checkable_strokeDash,
            float checkable_strokeDashGap,
            float checkable_radius,
            float checkable_radiusLT,
            float checkable_radiusLB,
            float checkable_radiusRT,
            float checkable_radiusRB,
            @ColorInt Integer checkable_startColor,
            @ColorInt Integer checkable_centerColor,
            @ColorInt Integer checkable_endColor,
            @Orientation int checkable_orientation,
            @GradientType int checkable_gradientType,
            Float checkable_radialCenterX,
            Float checkable_radialCenterY,
            float checkable_radialRadius,
            float checkable_width,
            float checkable_height,
            float checkable_marginLeft,
            float checkable_marginTop,
            float checkable_marginRight,
            float checkable_marginBottom,
            float checkable_ringThickness,
            float checkable_ringThicknessRatio,
            float checkable_ringInnerRadius,
            float checkable_ringInnerRadiusRatio,

            @ShapeMode int enabled_shapeMode,
            @ColorInt Integer enabled_solidColor,
            @ColorInt int enabled_strokeColor,
            float enabled_strokeWidth,
            float enabled_strokeDash,
            float enabled_strokeDashGap,
            float enabled_radius,
            float enabled_radiusLT,
            float enabled_radiusLB,
            float enabled_radiusRT,
            float enabled_radiusRB,
            @ColorInt Integer enabled_startColor,
            @ColorInt Integer enabled_centerColor,
            @ColorInt Integer enabled_endColor,
            @Orientation int enabled_orientation,
            @GradientType int enabled_gradientType,
            Float enabled_radialCenterX,
            Float enabled_radialCenterY,
            float enabled_radialRadius,
            float enabled_width,
            float enabled_height,
            float enabled_marginLeft,
            float enabled_marginTop,
            float enabled_marginRight,
            float enabled_marginBottom,
            float enabled_ringThickness,
            float enabled_ringThicknessRatio,
            float enabled_ringInnerRadius,
            float enabled_ringInnerRadiusRatio,

            @ShapeMode int focused_shapeMode,
            @ColorInt Integer focused_solidColor,
            @ColorInt int focused_strokeColor,
            float focused_strokeWidth,
            float focused_strokeDash,
            float focused_strokeDashGap,
            float focused_radius,
            float focused_radiusLT,
            float focused_radiusLB,
            float focused_radiusRT,
            float focused_radiusRB,
            @ColorInt Integer focused_startColor,
            @ColorInt Integer focused_centerColor,
            @ColorInt Integer focused_endColor,
            @Orientation int focused_orientation,
            @GradientType int focused_gradientType,
            Float focused_radialCenterX,
            Float focused_radialCenterY,
            float focused_radialRadius,
            float focused_width,
            float focused_height,
            float focused_marginLeft,
            float focused_marginTop,
            float focused_marginRight,
            float focused_marginBottom,
            float focused_ringThickness,
            float focused_ringThicknessRatio,
            float focused_ringInnerRadius,
            float focused_ringInnerRadiusRatio,

            @ShapeMode int pressed_shapeMode,
            @ColorInt Integer pressed_solidColor,
            @ColorInt int pressed_strokeColor,
            float pressed_strokeWidth,
            float pressed_strokeDash,
            float pressed_strokeDashGap,
            float pressed_radius,
            float pressed_radiusLT,
            float pressed_radiusLB,
            float pressed_radiusRT,
            float pressed_radiusRB,
            @ColorInt Integer pressed_startColor,
            @ColorInt Integer pressed_centerColor,
            @ColorInt Integer pressed_endColor,
            @Orientation int pressed_orientation,
            @GradientType int pressed_gradientType,
            Float pressed_radialCenterX,
            Float pressed_radialCenterY,
            float pressed_radialRadius,
            float pressed_width,
            float pressed_height,
            float pressed_marginLeft,
            float pressed_marginTop,
            float pressed_marginRight,
            float pressed_marginBottom,
            float pressed_ringThickness,
            float pressed_ringThicknessRatio,
            float pressed_ringInnerRadius,
            float pressed_ringInnerRadiusRatio,

            @ShapeMode int selected_shapeMode,
            @ColorInt Integer selected_solidColor,
            @ColorInt int selected_strokeColor,
            float selected_strokeWidth,
            float selected_strokeDash,
            float selected_strokeDashGap,
            float selected_radius,
            float selected_radiusLT,
            float selected_radiusLB,
            float selected_radiusRT,
            float selected_radiusRB,
            @ColorInt Integer selected_startColor,
            @ColorInt Integer selected_centerColor,
            @ColorInt Integer selected_endColor,
            @Orientation int selected_orientation,
            @GradientType int selected_gradientType,
            Float selected_radialCenterX,
            Float selected_radialCenterY,
            float selected_radialRadius,
            float selected_width,
            float selected_height,
            float selected_marginLeft,
            float selected_marginTop,
            float selected_marginRight,
            float selected_marginBottom,
            float selected_ringThickness,
            float selected_ringThicknessRatio,
            float selected_ringInnerRadius,
            float selected_ringInnerRadiusRatio,

            Drawable drawable,
            Drawable drawable_checked,
            Drawable drawable_checkable,
            Drawable drawable_enabled,
            Drawable drawable_focused,
            Drawable drawable_pressed,
            Drawable drawable_selected
    ) {
        boolean isDefaultNull = false;
        int count = 0;
        Drawable defaultDrawable = drawable != null ? drawable : create(
                shapeMode,
                solidColor,
                strokeColor,
                strokeWidth,
                strokeDash,
                strokeDashGap,
                radius,
                radiusLT,
                radiusLB,
                radiusRT,
                radiusRB,
                startColor,
                centerColor,
                endColor,
                orientation,
                gradientType,
                radialCenterX,
                radialCenterY,
                radialRadius,
                width,
                height,
                marginLeft,
                marginTop,
                marginRight,
                marginBottom,
                ringThickness,
                ringThicknessRatio,
                ringInnerRadius,
                ringInnerRadiusRatio
        );
        if (defaultDrawable != null) {
            count++;
        } else {
            isDefaultNull = true;
        }
        Drawable checkedDrawable = drawable_checked != null ? drawable_checked : create(
                checked_shapeMode,
                checked_solidColor,
                checked_strokeColor,
                checked_strokeWidth,
                checked_strokeDash,
                checked_strokeDashGap,
                checked_radius,
                checked_radiusLT,
                checked_radiusLB,
                checked_radiusRT,
                checked_radiusRB,
                checked_startColor,
                checked_centerColor,
                checked_endColor,
                checked_orientation,
                checked_gradientType,
                checked_radialCenterX,
                checked_radialCenterY,
                checked_radialRadius,
                checked_width,
                checked_height,
                checked_marginLeft,
                checked_marginTop,
                checked_marginRight,
                checked_marginBottom,
                checked_ringThickness,
                checked_ringThicknessRatio,
                checked_ringInnerRadius,
                checked_ringInnerRadiusRatio
        );
        if (checkedDrawable != null) {
            count++;
        }
        Drawable checkableDrawable = drawable_checkable != null ? drawable_checkable : create(
                checkable_shapeMode,
                checkable_solidColor,
                checkable_strokeColor,
                checkable_strokeWidth,
                checkable_strokeDash,
                checkable_strokeDashGap,
                checkable_radius,
                checkable_radiusLT,
                checkable_radiusLB,
                checkable_radiusRT,
                checkable_radiusRB,
                checkable_startColor,
                checkable_centerColor,
                checkable_endColor,
                checkable_orientation,
                checkable_gradientType,
                checkable_radialCenterX,
                checkable_radialCenterY,
                checkable_radialRadius,
                checkable_width,
                checkable_height,
                checkable_marginLeft,
                checkable_marginTop,
                checkable_marginRight,
                checkable_marginBottom,
                checkable_ringThickness,
                checkable_ringThicknessRatio,
                checkable_ringInnerRadius,
                checkable_ringInnerRadiusRatio
        );
        if (checkableDrawable != null) {
            count++;
        }
        Drawable enabledDrawable = drawable_enabled != null ? drawable_enabled : create(
                enabled_shapeMode,
                enabled_solidColor,
                enabled_strokeColor,
                enabled_strokeWidth,
                enabled_strokeDash,
                enabled_strokeDashGap,
                enabled_radius,
                enabled_radiusLT,
                enabled_radiusLB,
                enabled_radiusRT,
                enabled_radiusRB,
                enabled_startColor,
                enabled_centerColor,
                enabled_endColor,
                enabled_orientation,
                enabled_gradientType,
                enabled_radialCenterX,
                enabled_radialCenterY,
                enabled_radialRadius,
                enabled_width,
                enabled_height,
                enabled_marginLeft,
                enabled_marginTop,
                enabled_marginRight,
                enabled_marginBottom,
                enabled_ringThickness,
                enabled_ringThicknessRatio,
                enabled_ringInnerRadius,
                enabled_ringInnerRadiusRatio
        );
        if (enabledDrawable != null) {
            count++;
        }
        Drawable focusedDrawable = drawable_focused != null ? drawable_focused : create(
                focused_shapeMode,
                focused_solidColor,
                focused_strokeColor,
                focused_strokeWidth,
                focused_strokeDash,
                focused_strokeDashGap,
                focused_radius,
                focused_radiusLT,
                focused_radiusLB,
                focused_radiusRT,
                focused_radiusRB,
                focused_startColor,
                focused_centerColor,
                focused_endColor,
                focused_orientation,
                focused_gradientType,
                focused_radialCenterX,
                focused_radialCenterY,
                focused_radialRadius,
                focused_width,
                focused_height,
                focused_marginLeft,
                focused_marginTop,
                focused_marginRight,
                focused_marginBottom,
                focused_ringThickness,
                focused_ringThicknessRatio,
                focused_ringInnerRadius,
                focused_ringInnerRadiusRatio
        );
        if (focusedDrawable != null) {
            count++;
        }
        Drawable pressedDrawable = drawable_pressed != null ? drawable_pressed : create(
                pressed_shapeMode,
                pressed_solidColor,
                pressed_strokeColor,
                pressed_strokeWidth,
                pressed_strokeDash,
                pressed_strokeDashGap,
                pressed_radius,
                pressed_radiusLT,
                pressed_radiusLB,
                pressed_radiusRT,
                pressed_radiusRB,
                pressed_startColor,
                pressed_centerColor,
                pressed_endColor,
                pressed_orientation,
                pressed_gradientType,
                pressed_radialCenterX,
                pressed_radialCenterY,
                pressed_radialRadius,
                pressed_width,
                pressed_height,
                pressed_marginLeft,
                pressed_marginTop,
                pressed_marginRight,
                pressed_marginBottom,
                pressed_ringThickness,
                pressed_ringThicknessRatio,
                pressed_ringInnerRadius,
                pressed_ringInnerRadiusRatio
        );
        if (pressedDrawable != null) {
            count++;
        }
        Drawable selectedDrawable = drawable_selected != null ? drawable_selected : create(
                selected_shapeMode,
                selected_solidColor,
                selected_strokeColor,
                selected_strokeWidth,
                selected_strokeDash,
                selected_strokeDashGap,
                selected_radius,
                selected_radiusLT,
                selected_radiusLB,
                selected_radiusRT,
                selected_radiusRB,
                selected_startColor,
                selected_centerColor,
                selected_endColor,
                selected_orientation,
                selected_gradientType,
                selected_radialCenterX,
                selected_radialCenterY,
                selected_radialRadius,
                selected_width,
                selected_height,
                selected_marginLeft,
                selected_marginTop,
                selected_marginRight,
                selected_marginBottom,
                selected_ringThickness,
                selected_ringThicknessRatio,
                selected_ringInnerRadius,
                selected_ringInnerRadiusRatio
        );
        if (selectedDrawable != null) {
            count++;
        }
        if (count < 1) {
            // impossible，因为该方法被调用说明至少声明了一条属性
        } else {
            boolean needReSetPadding = false;
            if (isDefaultNull || count == 1) {
                // 当设置了margin（非view的margin）时，InsetDrawable会导致view本身的padding失效
                needReSetPadding = true;
                tmpPadding[0] = view.getPaddingLeft();
                tmpPadding[1] = view.getPaddingTop();
                tmpPadding[2] = view.getPaddingRight();
                tmpPadding[3] = view.getPaddingBottom();
            }
            if (count == 1 && !isDefaultNull) {
                view.setBackground(defaultDrawable);
            } else {
                ProxyDrawable listDrawable = new ProxyDrawable();
                if (checkedDrawable != null) {
                    listDrawable.addState(new int[]{android.R.attr.state_checked}, checkedDrawable);
                }
                if (checkableDrawable != null) {
                    listDrawable.addState(new int[]{android.R.attr.state_checkable}, checkableDrawable);
                }
                if (focusedDrawable != null) {
                    listDrawable.addState(new int[]{android.R.attr.state_focused}, focusedDrawable);
                }
                if (pressedDrawable != null) {
                    listDrawable.addState(new int[]{android.R.attr.state_pressed}, pressedDrawable);
                }
                if (selectedDrawable != null) {
                    listDrawable.addState(new int[]{android.R.attr.state_selected}, selectedDrawable);
                }
                if (enabledDrawable != null) {
                    listDrawable.addState(new int[]{android.R.attr.state_enabled}, enabledDrawable);
                }
                if (defaultDrawable != null) {
                    listDrawable.addState(new int[]{0}, defaultDrawable);
                } else {
                    Drawable originDrawable = view.getBackground();
                    if (originDrawable != null) {
                        if (originDrawable instanceof ProxyDrawable) {
                            originDrawable = ((ProxyDrawable) originDrawable).getOriginDrawable();
                        }
                        listDrawable.addState(new int[]{0}, originDrawable);
                    }
                }
                view.setBackground(listDrawable);
            }
            if (needReSetPadding) {
                view.setPadding(tmpPadding[0], tmpPadding[1], tmpPadding[2], tmpPadding[3]);
            }
        }
    }

    public static Drawable create(
            @ShapeMode int shapeMode, @ColorInt Integer solidColor,
            @ColorInt int strokeColor, @DP float strokeWidth, @DP float strokeDash, @DP float strokeDashGap,
            @DP float radius, @DP float radiusLT, @DP float radiusLB, @DP float radiusRT, @DP float radiusRB,
            @ColorInt Integer startColor, @ColorInt Integer centerColor, @ColorInt Integer endColor,
            @Orientation int orientation, @GradientType int gradientType,
            Float radialCenterX, Float radialCenterY, float radialRadius,
            @DP float width, @DP float height,
            @DP float marginLeft, @DP float marginTop, @DP float marginRight, @DP float marginBottom,
            @DP float ringThickness,
            @DP float ringThicknessRatio,
            @DP float ringInnerRadius,
            @DP float ringInnerRadiusRatio
    ) {
        if (shapeMode == INVALID && solidColor == null && strokeColor == INVALID
                && strokeWidth == INVALID && strokeDash == INVALID && strokeDashGap == INVALID
                && radius == INVALID && radiusLT == INVALID && radiusLB == INVALID
                && radiusRT == INVALID && radiusRB == INVALID && startColor == null
                && centerColor == null && endColor == null && orientation == INVALID
                && gradientType == INVALID && radialCenterX == null && radialCenterY == null
                && radialRadius == INVALID && width == INVALID && height == INVALID
                && marginLeft == INVALID && marginTop == INVALID && marginRight == INVALID && marginBottom == INVALID
        ) {
            // 这里需要判断empty，因为有可能只设置了一个state的drawable，那么其他state的就是empty了
            return null;
        }
        GradientDrawable drawable = new GradientDrawable();
        if (startColor != null && endColor != null) {
            int[] colors;
            if (centerColor != null) {
                colors = new int[3];
                colors[0] = startColor;
                colors[1] = centerColor;
                colors[2] = endColor;
            } else {
                colors = new int[2];
                colors[0] = startColor;
                colors[1] = endColor;
            }
            drawable.setColors(colors);
            drawable.setOrientation(mapOrientation(orientation));
            drawable.setGradientType(gradientType);
            if (gradientType == GradientType.RADIAL) {
                drawable.setGradientCenter(radialCenterX == null ? .5f : radialCenterX,
                        radialCenterY == null ? .5f : radialCenterY);
                drawable.setGradientRadius(dip2px(radialRadius));
            }
        } else {
            if (solidColor != null) {
                drawable.setColor(solidColor);
            }
        }
        drawable.setShape(validShapeMode(shapeMode));
        if (shapeMode == ShapeMode.RING) {
            // 由于GradientDrawable中没有ring相关的公开API，所以使用反射，若对性能有要求，请注意。
            setRingValue(drawable, ringThickness, ringThicknessRatio, ringInnerRadius, ringInnerRadiusRatio);
        }
        if (strokeWidth > 0) {
            drawable.setStroke(dip2px(strokeWidth), strokeColor, dip2px(strokeDash), dip2px(strokeDashGap));
        }
        if (radius <= 0) {
            float[] radiusEach = new float[]{dip2px(radiusLT), dip2px(radiusLT), dip2px(radiusRT), dip2px(radiusRT),
                    dip2px(radiusRB), dip2px(radiusRB), dip2px(radiusLB), dip2px(radiusLB)};
            drawable.setCornerRadii(radiusEach);
        } else {
            drawable.setCornerRadius(dip2px(radius));
        }
        if (width > 0 && height > 0) {
            // https://stackoverflow.com/a/29180660/4698946
            drawable.setSize(dip2px(width), dip2px(height));
        }
        if (marginLeft != 0 || marginTop != 0 || marginRight != 0 || marginBottom != 0) {
            return new InsetDrawable(drawable,
                    dip2px(marginLeft),
                    dip2px(marginTop),
                    dip2px(marginRight),
                    dip2px(marginBottom));
        } else {
            return drawable;
        }
    }

    private static int validShapeMode(@ShapeMode int shapeMode) {
        return shapeMode > ShapeMode.RING || shapeMode < ShapeMode.RECTANGLE
                ? GradientDrawable.RECTANGLE : shapeMode;
    }

    private static GradientDrawable.Orientation mapOrientation(@Orientation int orientation) {
        switch (orientation) {
            case Orientation.BL_TR:
                return GradientDrawable.Orientation.BL_TR;
            case Orientation.BOTTOM_TOP:
                return GradientDrawable.Orientation.BOTTOM_TOP;
            case Orientation.BR_TL:
                return GradientDrawable.Orientation.BR_TL;
            case Orientation.LEFT_RIGHT:
                return GradientDrawable.Orientation.LEFT_RIGHT;
            case Orientation.RIGHT_LEFT:
                return GradientDrawable.Orientation.RIGHT_LEFT;
            case Orientation.TL_BR:
                return GradientDrawable.Orientation.TL_BR;
            case Orientation.TOP_BOTTOM:
                return GradientDrawable.Orientation.TOP_BOTTOM;
            case Orientation.TR_BL:
                return GradientDrawable.Orientation.TR_BL;
        }
        return GradientDrawable.Orientation.TOP_BOTTOM;
    }

    private static void setRingValue(GradientDrawable drawable,
                                     Float thickness, Float thicknessRatio,
                                     Float innerRadius, Float innerRadiusRatio) {
        try {
            Field mGradientState = drawable.getClass().getDeclaredField("mGradientState");
            mGradientState.setAccessible(true);
            Class mGradientStateClass = mGradientState.get(drawable).getClass();
            Field mUseLevelForShape = mGradientStateClass.getDeclaredField("mUseLevelForShape");
            mUseLevelForShape.setAccessible(true);
            mUseLevelForShape.setBoolean(mGradientState.get(drawable), false);
            if (thickness != null) {
                Field mThickness = mGradientStateClass.getDeclaredField("mThickness");
                mThickness.setAccessible(true);
                mThickness.setInt(mGradientState.get(drawable), dip2px(thickness));
            }
            if (thicknessRatio != null) {
                Field mThicknessRatio = mGradientStateClass.getDeclaredField("mThicknessRatio");
                mThicknessRatio.setAccessible(true);
                mThicknessRatio.setFloat(mGradientState.get(drawable), dip2px(thicknessRatio));
            }
            if (innerRadius != null) {
                Field mInnerRadius = mGradientStateClass.getDeclaredField("mInnerRadius");
                mInnerRadius.setAccessible(true);
                mInnerRadius.setInt(mGradientState.get(drawable), dip2px(innerRadius));
            }
            if (innerRadiusRatio != null) {
                Field mInnerRadiusRatio = mGradientStateClass.getDeclaredField("mInnerRadiusRatio");
                mInnerRadiusRatio.setAccessible(true);
                mInnerRadiusRatio.setFloat(mGradientState.get(drawable), dip2px(innerRadiusRatio));
            }
        } catch (NoSuchFieldException t) {
            t.printStackTrace();
        } catch (IllegalAccessException t) {
            t.printStackTrace();
        }
    }

    private static int dip2px(float dipValue) {
        final float scale = Resources.getSystem().getDisplayMetrics().density;
        return (int) (dipValue * scale + .5f);
    }


    @IntDef({
            ShapeMode.RECTANGLE,
            ShapeMode.OVAL,
            ShapeMode.LINE,
            ShapeMode.RING,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface ShapeMode {
        int RECTANGLE = GradientDrawable.RECTANGLE;
        int OVAL = GradientDrawable.OVAL;
        /**
         * 画线时，有几点特性必须要知道的：
         * 1. 只能画水平线，画不了竖线；
         * 2. 线的高度是通过stroke的android:width属性设置的；
         * 3. size的android:height属性定义的是整个形状区域的高度；
         * 4. size的height必须大于stroke的width，否则，线无法显示；
         * 5. 线在整个形状区域中是居中显示的；
         * 6. 线左右两边会留有空白间距，线越粗，空白越大；
         * 7. 引用虚线的view需要添加属性android:layerType，值设为"software"，否则显示不了虚线。
         */
        int LINE = GradientDrawable.LINE;
        int RING = GradientDrawable.RING;
    }

    @IntDef({
            GradientType.LINEAR,
            GradientType.RADIAL,
            GradientType.SWEEP
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface GradientType {
        int LINEAR = 0;
        int RADIAL = 1;
        int SWEEP = 2;
    }

    @IntDef({
            Orientation.TOP_BOTTOM,
            Orientation.TR_BL,
            Orientation.RIGHT_LEFT,
            Orientation.BR_TL,
            Orientation.BOTTOM_TOP,
            Orientation.BL_TR,
            Orientation.LEFT_RIGHT,
            Orientation.TL_BR
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface Orientation {
        int TOP_BOTTOM = 0;
        int TR_BL = 1;
        int RIGHT_LEFT = 2;
        int BR_TL = 3;
        int BOTTOM_TOP = 4;
        int BL_TR = 5;
        int LEFT_RIGHT = 6;
        int TL_BR = 7;
    }

    @Retention(RetentionPolicy.SOURCE)
    @Target({PARAMETER, FIELD})
    @interface DP {
    }
}
