package com.ydl.ydlcommon.mvp.delegate

import android.app.Activity
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.View
import com.ydl.ydlcommon.mvp.base.IPresenter
import com.ydl.ydlcommon.mvp.base.IView
import com.ydl.ydlcommon.mvp.presenter.PresenterManager
import java.util.*
/**
 * Created by haorui on 2019-08-14.
 * Des: Fragment 生命周期委托类
 *      1. 初始化Presenter，回调Presenter中方法
 *      2. 实现Presenter缓存机制，防止横竖屏切换后Presenter多次重建
 */
open class MvpFragmentDelegateImpl<V : IView, P : IPresenter<V>>(
    protected var fragment: Fragment,
    private val delegateCallback: MvpDelegateCallback<V, P>,
    protected val keepPresenterInstance: Boolean
) {
    protected var mvpViewId: String? = null

    private val activity: Activity
        get() = fragment.activity ?: throw NullPointerException(
            "Fragment.getActivity() is null"
        )

    private val presenter: P
        get() = delegateCallback.getPresenter()

    private val mvpView: V
        get() = delegateCallback.getMvpView()

    fun onViewCreated(view: View, bundle: Bundle?) {
        val presenter = presenter
        presenter.attachView(mvpView)
    }

    fun onDestroyView() {
        presenter.detachView()
    }

    fun onSaveInstanceState(outState: Bundle?) {
        if (keepPresenterInstance && outState != null) {
            outState.putString(KEY_MVP_VIEW_ID, mvpViewId)
        }
    }

    fun onCreate(bundle: Bundle?) {
        var presenter: P?
        if (bundle != null && keepPresenterInstance) {
            //如果是改变页面配置导致的页面重建，取缓存的Presenter
            mvpViewId = bundle.getString(KEY_MVP_VIEW_ID)
            if (mvpViewId != null && ( PresenterManager.getPresenter<P>(activity, mvpViewId!!)) != null) {
                presenter =  PresenterManager.getPresenter<P>(activity, mvpViewId!!)
            } else {
                presenter = createViewIdAndCreatePresenter()
            }
        } else {
            presenter = createViewIdAndCreatePresenter()
        }
        if (presenter == null) {
            throw IllegalStateException(
                "Presenter 为空，请检查Presenter是否初始化."
            )
        }
        delegateCallback.setPresenter(presenter)
    }

    private fun createViewIdAndCreatePresenter(): P {
        val presenter = delegateCallback.createPresenter()
        if (keepPresenterInstance) {
            mvpViewId = UUID.randomUUID().toString()
            PresenterManager.putPresenter(activity, mvpViewId!!, presenter)
        }
        return presenter
    }

    fun onDestroy() {
        val activity = activity
        //如果为横竖屏切换导致的生命周期变动，保留Presenter实例
        val retainPresenterInstance = retainPresenterInstance(activity, fragment, keepPresenterInstance)
        val presenter = presenter
        if (!retainPresenterInstance) {
            presenter.destroy()
        }
        if (!retainPresenterInstance && mvpViewId != null) {
            //移除Presenter缓存
            PresenterManager.remove(activity, mvpViewId!!)
        }
    }

    companion object {
        protected const val KEY_MVP_VIEW_ID = "com.ydl.ydlcommon.core.fragment.mvp.id"

        internal fun retainPresenterInstance(activity: Activity, fragment: Fragment, keepPresenterInstance: Boolean): Boolean {
            if (activity.isChangingConfigurations) {
                return keepPresenterInstance
            }
            return if (activity.isFinishing) {
                false
            } else !fragment.isRemoving

        }
    }
}
