package com.ydl.ydlcommon.mvp.delegate

import android.app.Activity
import android.os.Bundle
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: Activity生命周期委托类
 *      1. 初始化Presenter，回调Presenter中方法
 *      2. 实现Presenter缓存机制，防止横竖屏切换后Presenter多次重建
 */
class MvpActivityDelegateImpl<V : IView, P : IPresenter<V>>(
    protected var activity: Activity,
    private val delegateCallback: MvpDelegateCallback<V, P>, protected var keepPresenterInstance: Boolean
) {
    protected var mvpViewId: String? = null

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

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

    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)
        presenter.attachView(mvpView)
    }

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

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

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

    companion object {

        protected const val KEY_Mvp_VIEW_ID = "com.ydl.ydlcommon.core.activity.mvp.id"

        internal fun retainPresenterInstance(keepPresenterInstance: Boolean, activity: Activity): Boolean {
            return keepPresenterInstance && (activity.isChangingConfigurations || !activity.isFinishing)
        }
    }
}
