package com.maniu.skin_lib;

import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;

/**
 * 拦截XML的生成过程  每个控件的实例化 就需要我们自己来做了
 * 收集需要换肤的控件
 */
public class SkinFactory implements LayoutInflater.Factory2 {
    //不管是什么控件  只要是原生 就一定是这个三个包下面的
    private static final String[] prxfixList = {
            "android.widget.",
            "android.view.",
            "android.webkit."
    };
    //装载需要换肤的控件的容器
    private List<SkinView> viewList = new ArrayList<>();

    @Override
    public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
        // 收集需要换肤的控件 实例化每个控件
        View view = null;
        //判断 这个控件的名字 是否有包名
        if(name.contains(".")){
            //代报名
            view = onCreateView(name,context,attrs);
        }else{
            //不带包名
            for (String s : prxfixList) {
                String viewName = s+name;
                view = onCreateView(viewName,context,attrs);
                if(view!=null){
                    break;
                }
            }
        }
        //收集需要换肤的控件 判断这个控件中有没有background 等等之类的用到了资源的属性
        if(view!=null){
            paserView(view,name,attrs);
        }
        return view;
    }

    public void apply(){
        for (SkinView skinView : viewList) {
            skinView.apply();
        }
    }

    /**
     * 收集控件的具体的方法
     * @param view
     * @param name
     * @param attrs
     */
    private void paserView(View view, String name, AttributeSet attrs) {
        //创建一个集合
        List<SkinItem> skinItems = new ArrayList<>();
        //遍历某个控件的所有的属性
        for(int x=0;x<attrs.getAttributeCount();x++){
            //获取到这条属性的名字 background
            String attributeName = attrs.getAttributeName(x);
            if(attributeName.contains("background") || attributeName.contains("src")
                    || attributeName.contains("textColor")){
                //获取到属性的值的资源ID @21212121
                String attributeValue = attrs.getAttributeValue(x);
                int resId = Integer.parseInt(attributeValue.substring(1));
                //获取到属性的值的名字 colorAccent
                String resourceEntryName = view.getResources().getResourceEntryName(resId);
                //获取到属性的值的类型@color
                String resourceTypeName = view.getResources().getResourceTypeName(resId);
                //先将这条属性封装为对象
                SkinItem skinItem = new SkinItem(attributeName,resourceTypeName,resourceEntryName,resId);
                skinItems.add(skinItem);
            }
        }
        if(skinItems.size()>0){
            SkinView skinView = new SkinView(view,skinItems);
            viewList.add(skinView);
        }
    }

    @Override
    public View onCreateView(String name, Context context, AttributeSet attrs) {
        View view = null;
        try {
            //得到控件的类对象
            Class aClass = context.getClassLoader().loadClass(name);
            //获取到控件的构造方法
            Constructor<? extends View> constructor = aClass.getConstructor(Context.class, AttributeSet.class);
            //通过构造方法 将控件实例化
            view = constructor.newInstance(context, attrs);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return view;
    }

    /**
     * 需要换肤的控件的封装duixiang
     */
    class SkinView{
        View view;
        //需要换肤的属性的集合
        List<SkinItem> skinItems;
        public SkinView(View view, List<SkinItem> skinItems) {
            this.view = view;
            this.skinItems = skinItems;
        }

        //对view进行资源切换
        public void apply(){
            for (SkinItem skinItem : skinItems) {
                //判断这条属性是background吗？
                if(skinItem.getName().equals("background")){
                    //1. 设置的是color颜色  2.设置的是图片
                    if(skinItem.getTypeName().equals("color")){
                        //将资源ID  传给ResouceManager  去进行资源匹配   如果匹配到了  就直接设置给控件
                        // 如果没有匹配到  就把之前的资源ID  设置控件
                        if(SkinManager.getInstance().resourceIsNull()){
                            view.setBackgroundResource(SkinManager.getInstance().getColor(skinItem.getResId()));
                        }else{
                            view.setBackgroundColor(SkinManager.getInstance().getColor(skinItem.getResId()));
                        }
                    }else if(skinItem.getTypeName().equals("drawable") || skinItem.getTypeName().equals("mipmap")){
                        if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.JELLY_BEAN){
                            view.setBackground(SkinManager.getInstance().getDrawable(skinItem.getResId()));
                        }else{
                            view.setBackgroundDrawable(SkinManager.getInstance().getDrawable(skinItem.getResId()));
                        }
                    }
                }else if(skinItem.getName().equals("src")){
                    if(skinItem.getTypeName().equals("drawable") || skinItem.getTypeName().equals("mipmap")){
                        //将资源ID  传给ResouceManager  去进行资源匹配   如果匹配到了  就直接设置给控件
                        // 如果没有匹配到  就把之前的资源ID  设置控件
                        ((ImageView)view).setImageDrawable(SkinManager.getInstance().getDrawable(skinItem.getResId()));
                    }
                }else if(skinItem.getName().equals("textColor")){
                    ((TextView)view).setTextColor(SkinManager.getInstance().getColor(skinItem.getResId()));
                }
            }
        }
    }


    /**
     * 每条属性的封装对象
     */
    class SkinItem{
        //属性的名字  textColor text background
        String name;
        //属性的值的类型 color mipmap
        String typeName;
        //属性的值的名字  colorPrimary
        String entryName;
        //属性的资源ID
        int resId;


        public SkinItem(String name, String typeName, String entryName, int resId) {
            this.name = name;
            this.typeName = typeName;
            this.entryName = entryName;
            this.resId = resId;
        }

        public String getName() {
            return name;
        }

        public String getTypeName() {
            return typeName;
        }

        public String getEntryName() {
            return entryName;
        }

        public int getResId() {
            return resId;
        }
    }
}
