package com.gh.gamecenter.common.base.fragment;

import static com.gh.gamecenter.common.constant.EntranceConsts.KEY_ENTRANCE;

import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import androidx.recyclerview.widget.RecyclerView;

import com.gh.gamecenter.common.BuildConfig;
import com.gh.gamecenter.common.R;
import com.gh.gamecenter.common.callback.OnListClickListener;
import com.gh.gamecenter.common.callback.OnRequestCallBackListener;
import com.gh.gamecenter.common.constant.Constants;
import com.gh.gamecenter.common.constant.EntranceConsts;
import com.gh.gamecenter.common.eventbus.EBMiPush;
import com.gh.gamecenter.common.syncpage.ISyncAdapterHandler;
import com.gh.gamecenter.common.syncpage.SyncDataEntity;
import com.gh.gamecenter.common.syncpage.SyncPageRepository;
import com.gh.gamecenter.common.utils.DarkModeUtils;
import com.lightgame.OnTitleClickListener;
import com.lightgame.utils.RuntimeUtils;
import com.lightgame.utils.Utils;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import kotlin.Pair;

/**
 * Created by LGT on 2016/9/4.
 * Fragment 基类
 */
public abstract class BaseFragment<T> extends Fragment implements OnRequestCallBackListener<T>,
        View.OnClickListener, OnListClickListener, OnTitleClickListener {

    public static final int RESULT_REFRESH = 9528;

    protected View mCachedView;

    protected boolean isEverPause;

    protected boolean mIsDarkModeOn;

    @NonNull
    protected String mEntrance = "";

    protected boolean mIsFromMainWrapper = false;
    protected boolean mIsFromTabWrapper = false;

    public long startPageTime = 0;

    protected final Handler mBaseHandler = new BaseFragment.BaseHandler(this);

    public static class BaseHandler extends Handler {
        private final WeakReference<BaseFragment> mFragmentWeakReference;

        BaseHandler(BaseFragment fragment) {
            mFragmentWeakReference = new WeakReference<>(fragment);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            BaseFragment fragment = mFragmentWeakReference.get();
            if (fragment != null) fragment.handleMessage(msg);
        }
    }

    protected void handleMessage(Message msg) {

    }

    @LayoutRes
    protected abstract int getLayoutId();

    /**
     * 提供 Inflated 的 view ，可用于 data binding.
     */
    protected View getInflatedLayout() {
        return null;
    }

    /**
     * 责任链，谁处理了就返回true，否则返回super.handleOnClick(View view)
     *
     * @return
     */
    protected boolean handleOnClick(View view) {
        return true;
    }

    @Override
    public void onClick(View v) {
        handleOnClick(v);
    }


    protected void initView(View view) {
        View mBackBtn = view.findViewById(R.id.backBtn);
        View mBackContainer = view.findViewById(R.id.backContainer);
        if (mBackBtn != null && mBackContainer != null) {
            mBackBtn.setOnClickListener(v -> requireActivity().onBackPressed());
            mBackContainer.setOnClickListener(v -> requireActivity().onBackPressed());
        }
    }

    protected void postRunnable(Runnable runnable) {
        RuntimeUtils.getInstance().runOnUiThread(runnable);
    }

    // 定时任务全部改用这个方法, 在onDestroy做统一取消定时
    protected void postDelayedRunnable(Runnable runnable, long delayMillis) {
        RuntimeUtils.getInstance().runOnUiThread(runnable, delayMillis);
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final Intent intent = getActivity().getIntent();
        mEntrance = intent.getStringExtra(KEY_ENTRANCE);
        if (getArguments() != null) {
            if (TextUtils.isEmpty(mEntrance)) {
                mEntrance = getArguments().getString(KEY_ENTRANCE);
            }
            mIsFromMainWrapper = getArguments().getBoolean(EntranceConsts.KEY_IS_FROM_MAIN_WRAPPER, false);
            mIsFromTabWrapper = getArguments().getBoolean(EntranceConsts.KEY_IS_FROM_TAB_WRAPPER, false);
        }

        if (TextUtils.isEmpty(mEntrance)) {
            mEntrance = Constants.ENTRANCE_UNKNOWN;
        }

        if (BuildConfig.DEBUG) {
            Utils.log("FRAGMENT_ENTRANCE -> " + mEntrance);
        }

        isEverPause = false;
        EventBus.getDefault().register(this);

        // For data binding.
        mCachedView = getInflatedLayout();
        if (mCachedView == null && getLayoutId() != 0) {
            mCachedView = View.inflate(getContext(), getLayoutId(), null);
        }

        if (mCachedView != null) {
            initView(mCachedView);
        }

        if (addSyncPageObserver()) {
            initSyncPageObserver();
        }
        mIsDarkModeOn = DarkModeUtils.INSTANCE.isDarkModeOn(requireContext());
    }

    private void initSyncPageObserver() {
        SyncPageRepository.INSTANCE.getSyncPageLiveData().observe(this, syncDataEntities -> {
            try {
                Utils.log("SyncPageRepository initSyncPageObserver->" + syncDataEntities);
                List<SyncDataEntity> readyRemoveList = new ArrayList<>();
                if (syncDataEntities == null || syncDataEntities.isEmpty()) return;
                RecyclerView.Adapter adapter = provideSyncAdapter();
                if (!(adapter instanceof ISyncAdapterHandler)) return;
                for (int i = 0; i < adapter.getItemCount(); i++) {
                    Pair<String, Object> syncKey = ((ISyncAdapterHandler) adapter).getSyncData(i);
                    if (syncKey == null) continue;
                    for (SyncDataEntity syncDataEntity : syncDataEntities) {
                        if (syncDataEntity.getSyncId().equals(syncKey.getFirst())) {
                            boolean isSuccess = SyncPageRepository.INSTANCE.handleSyncData(syncKey.getSecond(), syncDataEntity);
                            if (isSuccess) {
                                if (BuildConfig.DEBUG) {
                                    Utils.log("SyncPageRepository notify position->" + i);
                                }
                                adapter.notifyItemChanged(i);

                                if (syncDataEntity.getRemove()) {
                                    readyRemoveList.add(syncDataEntity);
                                }
                            }
                        }
                    }
                }

                mBaseHandler.postDelayed(() -> SyncPageRepository.removeSyncData(readyRemoveList), 2000);
            } catch (Exception e) {
                if (BuildConfig.DEBUG) {
                    throw e;
                } else {
                    e.printStackTrace();
                }
            }
        });
    }

    // 必须的有subscribe才能register
    @Subscribe(threadMode = ThreadMode.BACKGROUND)
    public void onDummyEvent(EBMiPush push) {

    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if (container != null) {
            container.removeView(mCachedView);
            // TODO 页面重建 (framgent 的重新获取) 有大问题，这里只是修修补补
            if (mCachedView != null && mCachedView.getParent() instanceof ViewGroup) {
                ((ViewGroup) mCachedView.getParent()).removeView(mCachedView);
            }
        }
        return mCachedView;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();

        mCachedView = null;
    }

    @Override
    public void onResume() {
        super.onResume();
        isEverPause = false;
        startPageTime = System.currentTimeMillis();

        if (!DarkModeUtils.INSTANCE.isFollowSystemDarkModeFromSp()
                && mIsDarkModeOn != DarkModeUtils.INSTANCE.isDarkModeOn(requireContext())) {
            onDarkModeChanged();
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        isEverPause = true;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mBaseHandler.removeCallbacksAndMessages(null);
        RuntimeUtils.getInstance().removeRunnable();
        EventBus.getDefault().unregister(this);
    }

    public void toast(@StringRes int res) {
        toast(getString(res));
    }

    public void toast(String msg) {
        Utils.toast(getContext(), msg);
    }

    public void toastLong(@StringRes int msg) {
        toastLong(getString(msg));
    }

    public void toastLong(String msg) {
        RuntimeUtils.getInstance().toastLong(getContext(), msg);
    }

    public boolean isEverPause() {
        return isEverPause;
    }

    @Override
    public void loadDone() {
        // do nothing
    }

    @Override
    public void loadDone(T obj) {
        // do nothing
    }

    @Override
    public void loadError() {
        // do nothing
    }

    @Override
    public void loadEmpty() {
        // do nothing
    }

    @Override
    public void loadNotFound() {
        // do nothing
    }

    @Override
    public <LIST> void onListClick(View view, int position, LIST data) {

    }

    protected <K> Observable<K> asyncCall(Observable<K> observable) {
        return observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }

    // 将所有的Fragment都置为隐藏状态。
    protected void hideFragments(FragmentTransaction transaction) {
        List<Fragment> list = getChildFragmentManager().getFragments();
        for (Fragment fragment : list) {
            transaction.hide(fragment);
        }
    }

    @Override
    public void onTitleClick() {
        List<Fragment> list = getChildFragmentManager().getFragments();
        for (Fragment fragment : list) {
            if (fragment instanceof OnTitleClickListener) {
                ((OnTitleClickListener) fragment).onTitleClick();
            }
        }
    }

    // 为 fragment 附加 bundle (setArgument())
    public BaseFragment with(Bundle bundle) {
        if (!isStateSaved()) {
            this.setArguments(bundle);
        }
        return this;
    }

    public void onParentActivityFinish() {

    }

    @Nullable
    protected RecyclerView.Adapter provideSyncAdapter() {
        return null;
    }

    protected boolean addSyncPageObserver() {
        return false;
    }

    @Override
    public void onConfigurationChanged(@NonNull Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

        if (mIsDarkModeOn != DarkModeUtils.INSTANCE.isDarkModeOn(requireContext())) {
            mIsDarkModeOn = DarkModeUtils.INSTANCE.isDarkModeOn(requireContext());
            onDarkModeChanged();
        }
    }

    protected void onDarkModeChanged() {

    }
}
