package com.mogo.skin;

import android.graphics.Typeface;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.core.view.ViewCompat;

import com.mogo.skin.utils.SkinResources;
import com.mogo.skin.utils.SkinThemeUtils;

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

/**
 *  donghongyu
 */
public class SkinAttribute {

    private static final List<String> mAttributes = new ArrayList<>();

    static {
        mAttributes.add("background");
        mAttributes.add("src");

        mAttributes.add("textColor");
        mAttributes.add("textColorHint");
        mAttributes.add("drawableLeft");
        mAttributes.add("drawableTop");
        mAttributes.add("drawableRight");
        mAttributes.add("drawableBottom");

        mAttributes.add("skinTypeface");

        mAttributes.add("text");
        mAttributes.add("hint");
    }

    private Typeface typeface;

    private static final String TAG = "SkinAttribute";

    List<SkinView> mSkinViews = new ArrayList<>();

    public SkinAttribute(Typeface typeface) {
        this.typeface = typeface;
    }

    public void load(View view, AttributeSet attrs) {
        List<SkinPair> skinPairs = new ArrayList<>();
        for (int i = 0; i < attrs.getAttributeCount(); i++) {
            //获得属性名
            String attributeName = attrs.getAttributeName(i);
            //是否符合 需要筛选的属性名
            if (mAttributes.contains(attributeName)) {
                String attributeValue = attrs.getAttributeValue(i);
                //写死了，不管了
                if (attributeValue.startsWith("#")) {
                    continue;
                }
                //资源id
                int resId = 0;
                if (attributeValue.startsWith("?")) {
                    //attr Id
                    int attrId = Integer.parseInt(attributeValue.substring(1));
                    //获得 主题 style 中的 对应 attr 的资源id值
                    resId = SkinThemeUtils.getResId(view.getContext(), new int[]{attrId})[0];
                } else {
                    try {
                        // @12343455332
                        if (isNumeric(attributeValue.substring(1))) {
                            resId = Integer.parseInt(attributeValue.substring(1));
                        }
                    } catch (NumberFormatException e) {
                        // 由于有时候TextView会直接配置文字，而不是用 @string/XXX 所以会导致这里转换异常，车里简单的处理异常跳过即可
                        //e.printStackTrace();
                    }
                }
                if (resId != 0) {
                    //可以被替换的属性
                    SkinPair skinPair = new SkinPair(attributeName, resId);
                    skinPairs.add(skinPair);
                }
            }
        }

        //将View与之对应的可以动态替换的属性集合 放入 集合中
        if (!skinPairs.isEmpty() || view instanceof TextView || view instanceof SkinViewSupport) {
            SkinView skinView = new SkinView(view, skinPairs);
            skinView.applySkin(typeface);
            mSkinViews.add(skinView);
        }
    }

    public static boolean isNumeric(String str) {
        if (str == null) {
            return false;
        }
        return str.matches("-?\\d+(\\.\\d+)?"); // 匹配整数或小数
    }

    /**
     * 换皮肤
     */
    public void applySkin(Typeface typeface) {
        for (SkinView mSkinView : mSkinViews) {
            mSkinView.applySkin(typeface);
        }
    }

    static class SkinView {

        View view;
        List<SkinPair> skinPairs;

        public SkinView(View view, List<SkinPair> skinPairs) {
            this.view = view;
            this.skinPairs = skinPairs;
        }

        /**
         * @param typeface 字体
         */
        public void applySkin(Typeface typeface) {
            applySkinTypeface(typeface);
            applySkinViewSupport();
            for (SkinPair skinPair : skinPairs) {
                Drawable left = null, top = null, right = null, bottom = null;
                String textStr;
                switch (skinPair.attributeName) {
                    case "background":
                        Object background = SkinResources.getInstance().getBackground(skinPair.resId);
                        //Color
                        if (background instanceof Integer) {
                            view.setBackgroundColor((Integer) background);
                        } else {
                            ViewCompat.setBackground(view, (Drawable) background);
                        }
                        break;
                    case "src":
                        background = SkinResources.getInstance().getBackground(skinPair.resId);
                        if (background instanceof Integer) {
                            ((ImageView) view).setImageDrawable(new ColorDrawable((Integer) background));
                        } else {
                            ((ImageView) view).setImageDrawable((Drawable) background);
                        }
                        break;
                    case "textColor":
                        ((TextView) view).setTextColor(SkinResources.getInstance().getColorStateList(skinPair.resId));
                        break;
                    case "textColorHint":
                        ((EditText) view).setHintTextColor(SkinResources.getInstance().getColorStateList(skinPair.resId));
                        break;
                    case "drawableLeft":
                        left = SkinResources.getInstance().getDrawable(skinPair.resId);
                        break;
                    case "drawableTop":
                        top = SkinResources.getInstance().getDrawable(skinPair.resId);
                        break;
                    case "drawableRight":
                        right = SkinResources.getInstance().getDrawable(skinPair.resId);
                        break;
                    case "drawableBottom":
                        bottom = SkinResources.getInstance().getDrawable(skinPair.resId);
                        break;
                    case "skinTypeface":
                        Typeface typeface1 = SkinResources.getInstance().getTypeface(skinPair.resId);
                        applySkinTypeface(typeface1);
                        break;
                    case "text":
                        textStr = SkinResources.getInstance().getString(skinPair.resId);
                        applyText(textStr);
                        break;
                    case "hint":
                        textStr = SkinResources.getInstance().getString(skinPair.resId);
                        applyHintText(textStr);
                        break;
                    default:
                        break;
                }
                if (null != left || null != right || null != top || null != bottom) {
                    ((TextView) view).setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);
                }
            }
        }

        private static Handler mHandler = new Handler(Looper.getMainLooper());

        private void applySkinViewSupport() {
            if (view instanceof SkinViewSupport) {
                ((SkinViewSupport) view).applySkin();
            }
        }

        private void applySkinTypeface(final Typeface typeface) {
            if (view instanceof TextView) {
                Log.d(TAG, "applySkinTypeface() called with: view = [" + ((TextView) view).getText() + "]  Parent = " + view.getParent());
                //post 防止某些控件的属性设置是在构造函数调用完成之后进行的。
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        ((TextView) view).setTypeface(typeface);
                    }
                });
            }
        }

        private void applyText(final String textStr) {
            if (view instanceof TextView) {
                Log.d(TAG, "applyText() called with: view = [" + ((TextView) view).getText() + "]  Parent = " + view.getParent());
                //post 防止某些控件的属性设置是在构造函数调用完成之后进行的。
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        ((TextView) view).setText(textStr);
                    }
                });
            }
        }

        private void applyHintText(final String textStr) {
            if (view instanceof EditText) {
                Log.d(TAG, "applyHintText() called with: view = [" + ((TextView) view).getText() + "]  Parent = " + view.getParent());
                //post 防止某些控件的属性设置是在构造函数调用完成之后进行的。
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        ((EditText) view).setHint(textStr);
                    }
                });
            }
        }

    }

    static class SkinPair {

        String attributeName;
        int resId;

        public SkinPair(String attributeName, int resId) {
            this.attributeName = attributeName;
            this.resId = resId;
        }
    }

}
