package com.doumee.lib_coremodel.base;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.os.Message;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.Window;
import android.view.WindowManager;
import android.webkit.WebView;
import android.widget.PopupWindow;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StyleRes;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityOptionsCompat;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelProviders;
import androidx.lifecycle.ViewModelStoreOwner;
import com.gyf.immersionbar.BarHide;
import com.gyf.immersionbar.ImmersionBar;
import com.doumee.lib_coremodel.R;
import com.doumee.lib_coremodel.base.livedata.ActionEvent;
import com.doumee.lib_coremodel.base.livedata.MessageEvent;
import com.doumee.lib_coremodel.base.livedata.StatusEvent;
import com.doumee.lib_coremodel.bean.event.ActionEventData;
import com.doumee.lib_coremodel.bean.event.TagEvent;
import com.doumee.lib_coremodel.view.ToastView;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
 * MVVMFrame 框架基于Google官方的 JetPack 构建,在使用MVVMFrame时,需遵循一些规范:
 *
 * 如果您继承使用了BaseActivity或其子类,你需要参照如下方式添加@AndroidEntryPoint注解
 *
 * @example Activity
 * //-------------------------
 *    @AndroidEntryPoint
 *    public class YourActivity extends BaseActivity {
 *
 *    }
 * //-------------------------
 *
 * @author Jenly
 */
public abstract class BaseActivity extends AppCompatActivity implements IView, BaseNavigator {
    protected String tag;//设置标志;
    /**
     * 请通过 {@link #getVM()}获取,后续版本 {@link #mViewModel}可能会私有化
     */
    private VM mViewModel;
    /**
     * 请通过 {@link #getDB()}获取,后续版本 {@link #mBinding}可能会私有化
     */
    private VDB mBinding;
    protected static final float DEFAULT_WIDTH_RATIO = 0.85f;
    private Dialog mDialog;
    public Context mContext;
    private Toast toast;
    protected BaseProgressDialog mProgressDialog;
    public boolean isNeedSetNomalBar=true;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initContentView();
        if(!EventBus.getDefault().isRegistered(this)){
            EventBus.getDefault().register(this);
        }
        mContext=this;
        initViewModel();
        initView(savedInstanceState);
        initData(savedInstanceState);
        tag = getStringFormBundle("tag");
        getVM().setTag(tag);
    }
    /**
     * 初始化ContentView,{@link #setContentView(int)} }
     */
    protected void initContentView(){
        if(isBinding()){
            mBinding = DataBindingUtil.setContentView(this,getLayoutId());
        }else{
            setContentView(getLayoutId());
        }
    }
    /**
     * 初始化 {@link #mViewModel}
     */
    private void initViewModel(){
        mViewModel = createViewModel();
        if(mViewModel != null){
            getLifecycle().addObserver(mViewModel);
            registerLoadingEvent();
        }
    }
    protected void init(){
        setImmersionBar();
        normalConfig();
    }
    public int getIntFormBundle(String key){
        if(getIntent().getExtras()!=null){
            return getIntent().getExtras().getInt(key);
        }
        return 0;
    }
    public String getStringFormBundle(String key){
        if(getIntent().getExtras()!=null){
            return getIntent().getExtras().getString(key);
        }
        return "";
    }
    public void normalConfig(){
        registerNormal();
        getVM().setLifecycleOwner(this);
        setImmersionBarFullScreen();
    }
    protected void setImmersionBar(){
        //沉浸式状态栏
        ImmersionBar.with(this).statusBarColor(R.color.transparent)
                .statusBarDarkFont(true)
                .fitsSystemWindows(true)
                .init();
    }
    protected void setImmersionBarFullScreen(){
        ImmersionBar.with(this)
                .statusBarColor(R.color.transparent)
                .hideBar(BarHide.FLAG_HIDE_STATUS_BAR)
                .statusBarDarkFont(true)
                .init();
    }
    private Class getVMClass(){
        Class cls = getClass();
        Class vmClass = null;
        while (vmClass == null && cls!= null){
            vmClass = getVMClass(cls);
            cls = cls.getSuperclass();
        }
        if(vmClass == null){
            vmClass = (Class) BaseViewModel.class;
        }
        return vmClass;
    }
    private Class getVMClass(Class cls){
        Type type = cls.getGenericSuperclass();
        if(type instanceof ParameterizedType){
            Type[] types = ((ParameterizedType)type).getActualTypeArguments();
            for(Type t : types){
                if(t instanceof Class){
                    Class vmClass = (Class)t;
                    if(BaseViewModel.class.isAssignableFrom(vmClass)){
                        return vmClass;
                    }
                }else if(t instanceof ParameterizedType){
                    Type rawType = ((ParameterizedType)t).getRawType();
                    if(rawType instanceof Class){
                        Class vmClass = (Class)rawType;
                        if(BaseViewModel.class.isAssignableFrom(vmClass)){
                            return vmClass;
                        }
                    }
                }
            }
        }
        return null;
    }
    @Subscribe
    public void LogOutEvent(LogOutEvent event){
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(EventBus.getDefault().isRegistered(this)){
            EventBus.getDefault().unregister(this);
        }
        if(mViewModel != null){
            getLifecycle().removeObserver(mViewModel);
            mViewModel = null;
        }
        if(toast!=null){
            toast.cancel();
            toast = null;
        }
        if(mBinding != null){
            mBinding.unbind();
        }
    }
    // 如果你的app可以横竖屏切换,并且适配4.4或者emui3手机请务必在onConfigurationChanged方法里添加这句话
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        ImmersionBar.with(this).init();
    }
    /**
     * 注册动作事件
     */
    protected void registerActionEvent(ActionEvent.ActionObserver observer){
        mViewModel.getActionEvent().observe(this, observer);
    }
    /**
     * 注册状态加载事件
     */
    protected void registerLoadingEvent(){
        mViewModel.getLoadingEvent().observe(this, new Observer() {
            @Override
            public void onChanged(@Nullable Boolean isLoading) {
                if(isLoading){
                    showLoading();
                }else{
                    hideLoading();
                }
            }
        });
    }
    public void registerNormal(){
        registerActionEvent(new ActionEvent.ActionObserver() {
            @Override
            public void onStatusChanged(ActionEventData data) {
                switch (data.getAction()){
                    case ActionEvent.Action.FINISH:
                        finish();
                        break;
                    case ActionEvent.Action.START_ACTIVITY:
                        startActivity(data.getClassFromData(), data.getBundleFromData());
                        break;
                    case ActionEvent.Action.TOAST:
                        if(toast!=null){
                            toast.cancel();
                        }
                        toast = ToastView.show(getApplicationContext(), (String) data.getData().get("toast"));
                        //Toast.makeText(getContext(), data.getBundleFromData().getString("toast"), Toast.LENGTH_SHORT).show();
                        break;
                    default:
                        otherRegister(data);
                        break;
                }
            }
        });
    }
    protected void otherRegister(ActionEventData data){
        switch (data.getAction()){
            case ActionEvent.Action.DO:
                int type = (int) data.getData().get("type");
                doRegister(type,data);
                break;
            default:
                break;
        }
    }
    protected void doRegister(int type,ActionEventData data){
    }
    @Override
    public void showLoading() {
        showProgressDialog();
    }
    @Override
    public void hideLoading() {
        dismissProgressDialog();
    }
    /**
     * 注册消息事件
     */
    protected void registerMessageEvent(@NonNull MessageEvent.MessageObserver observer){
        getVM().getMessageEvent().observe(this,observer);
    }
    /**
     * 注册单个消息事件,消息对象:{@link Message}
     * @param observer
     */
    protected void registerSingleLiveEvent(@NonNull Observer observer){
        getVM().getSingleLiveEvent().observe(this,observer);
    }
    /**
     * 注册状态事件
     * @param observer
     */
    protected void registerStatusEvent(@NonNull StatusEvent.StatusObserver observer){
        getVM().getStatusEvent().observe(this,observer);
    }
    public Context getContext(){
        return this;
    }
    /**
     * 是否使用DataBinding
     * @return  默认为true 表示使用。如果为false,则不会初始化 {@link #mBinding}。
     */
    @Override
    public boolean isBinding(){
        return true;
    }
    /**
     * 创建ViewModel
     * @return {@link #mViewModel}会默认根据当前Activity泛型 {@link VM}获得ViewModel
     */
    @Override
    public VM createViewModel(){
        return obtainViewModel(getVMClass());
    }
    /**
     * 获取 ViewModel
     * @return {@link #mViewModel}
     */
    public VM getVM(){
        return mViewModel;
    }
    /**
     * 获取 ViewDataBinding
     * @return {@link #mBinding}
     */
    public VDB getDB(){
        return mBinding;
    }
    /**
     * 通过 {@link #createViewModelProvider(ViewModelStoreOwner)}获得 ViewModel
     * @param modelClass
     * @param 
     * @return
     */
    public  T obtainViewModel(@NonNull Class modelClass){
        return createViewModelProvider(this).get(modelClass);
        //return ViewModelProviders.of(this).get(modelClass);
        /*return new ViewModelProvider(
                this,
                ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication())
        ).get(modelClass);*/
    }
    /**
     * @deprecated 请使用 {@link #obtainViewModel(Class)}
     * @param modelClass
     * @param 
     * @return
     */
    @Deprecated
    public  T getVM(@NonNull Class modelClass){
        return obtainViewModel(modelClass);
    }
    /**
     * 创建 {@link ViewModelProvider}
     * @param owner
     * @return
     */
    private ViewModelProvider createViewModelProvider(@NonNull ViewModelStoreOwner owner){
        return new ViewModelProvider(owner);
    }
    //---------------------------------------
    protected Intent newIntent(Class> cls){
        return new Intent(getContext(),cls);
    }
    protected Intent newIntent(Class> cls, int flags){
        Intent intent = newIntent(cls);
        intent.addFlags(flags);
        return intent;
    }
    protected void startActivity(Class> cls){
        startActivity(newIntent(cls));
    }
    /**
     * 跳转页面
     *
     * @param clz    所跳转的目的Activity类
     * @param bundle 跳转所携带的信息
     */
    public void startActivity(Class> clz, Bundle bundle) {
        Intent intent = new Intent(this, clz);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        startActivity(intent);
    }
    protected void startActivity(Class> cls, int flags){
        startActivity(newIntent(cls,flags));
    }
    protected void startActivity(Class> cls, @Nullable ActivityOptionsCompat optionsCompat){
        startActivity(newIntent(cls),optionsCompat);
    }
    protected void startActivity(Class> cls, int flags, @Nullable ActivityOptionsCompat optionsCompat){
        startActivity(newIntent(cls,flags),optionsCompat);
    }
    protected void startActivity(Intent intent, @Nullable ActivityOptionsCompat optionsCompat){
        if(optionsCompat != null){
            startActivity(intent,optionsCompat.toBundle());
        }else{
            startActivity(intent);
        }
    }
    protected void startActivityFinish(Class> cls){
        startActivity(cls);
        finish();
    }
    protected void startActivityFinish(Class> cls, int flags){
        startActivity(cls,flags);
        finish();
    }
    protected void startActivityFinish(Class> cls, @Nullable ActivityOptionsCompat optionsCompat){
        startActivity(cls,optionsCompat);
        finish();
    }
    protected void startActivityFinish(Class> cls, int flags, @Nullable ActivityOptionsCompat optionsCompat){
        startActivity(newIntent(cls,flags),optionsCompat);
    }
    protected void startActivityFinish(Intent intent, @Nullable ActivityOptionsCompat optionsCompat){
        startActivity(intent,optionsCompat);
    }
    protected void startActivityForResult(Class> cls, int requestCode){
        startActivityForResult(newIntent(cls),requestCode);
    }
    protected void startActivityForResult(Class> cls, int requestCode, @Nullable ActivityOptionsCompat optionsCompat){
        Intent intent = newIntent(cls);
        if(optionsCompat != null){
            startActivityForResult(intent,requestCode,optionsCompat.toBundle());
        }else{
            startActivityForResult(intent,requestCode);
        }
    }
    //---------------------------------------
    protected View inflate(@LayoutRes int id){
        return inflate(id,null);
    }
    protected View inflate(@LayoutRes int id, @Nullable ViewGroup root){
        return LayoutInflater.from(getContext()).inflate(id,root);
    }
    protected View inflate(@LayoutRes int id, @Nullable ViewGroup root, boolean attachToRoot){
        return LayoutInflater.from(getContext()).inflate(id,root,attachToRoot);
    }
    //---------------------------------------
    protected void showDialogFragment(DialogFragment dialogFragment){
        String tag = dialogFragment.getTag() !=null ? dialogFragment.getTag() : dialogFragment.getClass().getSimpleName();
        showDialogFragment(dialogFragment,tag);
    }
    protected void showDialogFragment(DialogFragment dialogFragment, String tag) {
        dialogFragment.show(getSupportFragmentManager(),tag);
    }
    protected void showDialogFragment(DialogFragment dialogFragment, FragmentManager fragmentManager, String tag) {
        dialogFragment.show(fragmentManager,tag);
    }
    private View.OnClickListener mOnDialogCancelClick = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            dismissDialog();
        }
    };
    protected Dialog getDialog(){
        return this.mDialog;
    }
    protected Dialog getProgressDialog(){
        return this.mProgressDialog;
    }
    protected View.OnClickListener getDialogCancelClick(){
        return mOnDialogCancelClick;
    }
    protected void dismissDialog(){
        dismissDialog(mDialog);
    }
    protected void dismissDialog(Dialog dialog){
        if(dialog != null && dialog.isShowing()){
            dialog.dismiss();
        }
    }
    protected void dismissPopupWindow(PopupWindow popupWindow){
        if(popupWindow!=null && popupWindow.isShowing()){
            popupWindow.dismiss();
        }
    }
    protected void dismissProgressDialog(){
        dismissDialog(mProgressDialog);
    }
    protected void showProgressDialog(){
        showProgressDialog(true);
    }
    protected void showProgressDialog(boolean isCancel){
        showProgressDialog(R.layout.mvvmframe_progress_dialog,isCancel);
    }
    protected void showProgressDialog(@LayoutRes int resId){
        showProgressDialog(resId,false);
    }
    protected void showProgressDialog(@LayoutRes int resId,boolean isCancel){
        showProgressDialog(inflate(resId),isCancel);
    }
    protected void showProgressDialog(View v){
        showProgressDialog(v,false);
    }
    protected void showProgressDialog(View v, boolean isCancel){
        dismissProgressDialog();
        mProgressDialog =  BaseProgressDialog.newInstance(getContext());
        mProgressDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.WHITE));
        mProgressDialog.setContentView(v);
        mProgressDialog.setCanceledOnTouchOutside(isCancel);
        mProgressDialog.show();
        /*try {
            mProgressDialog = ProgressDialog.show(this, "", );
            mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
            mProgressDialog.setCancelable(isCancel);
            mProgressDialog.show();
        } catch (Exception e) {
            e.printStackTrace();
        }*/
    }
    protected void showDialog(View contentView){
        showDialog(contentView,DEFAULT_WIDTH_RATIO);
    }
    protected void showDialog(View contentView, boolean isCancel){
        showDialog(getContext(),contentView,R.style.mvvmframe_dialog,DEFAULT_WIDTH_RATIO,isCancel);
    }
    protected void showDialog(View contentView, float widthRatio){
        showDialog(getContext(),contentView,widthRatio);
    }
    protected void showDialog(View contentView, float widthRatio, boolean isCancel){
        showDialog(getContext(),contentView,R.style.mvvmframe_dialog,widthRatio,isCancel);
    }
    protected void showDialog(Context context, View contentView, float widthRatio){
        showDialog(context,contentView, R.style.mvvmframe_dialog,widthRatio);
    }
    protected void showDialog(Context context, View contentView, @StyleRes int resId, float widthRatio){
        showDialog(context,contentView,resId,widthRatio,true);
    }
    protected void showDialog(Context context, View contentView, @StyleRes int resId, float widthRatio, final boolean isCancel){
        dismissDialog();
        mDialog = new Dialog(context,resId);
        mDialog.setContentView(contentView);
        mDialog.setCanceledOnTouchOutside(false);
        mDialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
            @Override
            public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
                if(keyCode == KeyEvent.KEYCODE_BACK){
                    if(isCancel){
                        dismissDialog();
                    }
                    return true;
                }
                return false;
            }
        });
        setDialogWindow(mDialog,widthRatio);
        mDialog.show();
    }
    protected void setDialogWindow(Dialog dialog, float widthRatio){
        setWindow(dialog.getWindow(),widthRatio);
    }
    protected void setWindow(Window window, float widthRatio){
        WindowManager.LayoutParams lp = window.getAttributes();
        lp.width = (int)(getWidthPixels() * widthRatio);
        window.setAttributes(lp);
    }
    //---------------------------------------
    protected DisplayMetrics getDisplayMetrics(){
        return getResources().getDisplayMetrics();
    }
    protected int getWidthPixels(){
        return getDisplayMetrics().widthPixels;
    }
    protected int getHeightPixels(){
        return getDisplayMetrics().heightPixels;
    }
    public void destroyWebView(WebView webView){
        if (webView != null) {
            webView.clearCache(true);
            webView.clearHistory();
            webView.removeAllViews();
            // 如果先调用destroy()方法,则会命中if (isDestroyed()) return;这一行代码,需要先onDetachedFromWindow(),再
            // destory()
            ViewParent parent = webView.getParent();
            if (parent != null) {
                ((ViewGroup) parent).removeView(webView);
            }
            webView.stopLoading();
            // 退出时调用此方法,移除绑定的服务,否则某些特定系统会报错
            webView.getSettings().setJavaScriptEnabled(false);
            webView.clearHistory();
            webView.clearView();
            webView.removeAllViews();
            try {
                webView.destroy();
            } catch (Throwable ex) {
            }
        }
    }
    @Subscribe
    public void TagEvent(TagEvent event){
        if(!TextUtils.isEmpty(tag)&&event.getTag().equals(tag)){
            finish();
        }
    }
}