package com.develop.food.base.utils

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment

/**
 * 规避了内存重建重复添加的Fragment添加工具
 */
object FragmentKit {
    fun <T : Fragment?> addFragment(
        host: AppCompatActivity,
        fragmentClz: Class<T>,
        containerId: Int,
        needUpdateData: Boolean = false
    ): T {
        return addFragment(host, fragmentClz, containerId, null, needUpdateData)
    }

    private fun <T : Fragment?> addFragment(
        host: AppCompatActivity,
        fragmentClz: Class<T>,
        containerId: Int,
        data: Bundle?,
        needUpdateData: Boolean = false
    ): T {
        val fragmentTag = fragmentClz.name
        var fragment =
            host.supportFragmentManager.findFragmentByTag(fragmentTag)
        if (fragment != null) {
            if (needUpdateData) fragment.arguments = data
            return fragment as T
        }
        fragment = host.supportFragmentManager
            .fragmentFactory
            .instantiate(host.classLoader, fragmentClz.name)
        if (data != null) {
            fragment.arguments = data
        }
        host.supportFragmentManager
            .beginTransaction()
            .add(containerId, fragment, fragmentTag)
            .commitAllowingStateLoss()
        return fragment as T
    }

    fun <T : Fragment?> replaceFragment(
        host: AppCompatActivity,
        fragmentClz: Class<T>,
        containerId: Int,
        needUpdateData: Boolean = false
    ): T {
        return replaceFragment(host, fragmentClz, containerId, null, needUpdateData)
    }

    fun <T : Fragment?> replaceFragment(
        host: AppCompatActivity,
        fragmentClz: Class<T>,
        containerId: Int,
        data: Bundle?,
        needUpdateData: Boolean
    ): T {
        val fragmentTag = fragmentClz.name
        var fragment =
            host.supportFragmentManager.findFragmentByTag(fragmentTag)
        if (fragment != null) {
            if (needUpdateData) fragment.arguments = data
            return fragment as T
        }
        fragment = host.supportFragmentManager
            .fragmentFactory
            .instantiate(host.classLoader, fragmentClz.name)
        if (data != null) {
            fragment.arguments = data
        }
        host.supportFragmentManager
            .beginTransaction()
            .replace(containerId, fragment, fragmentTag)
            .commitAllowingStateLoss()
        return fragment as T
    }

    fun <T : Fragment?> hideFragment(
        host: AppCompatActivity,
        fragmentClz: Class<T>,
    ): T {
        val fragmentTag = fragmentClz.name
        var fragment =
            host.supportFragmentManager.findFragmentByTag(fragmentTag)
        if (fragment != null) {
            host.supportFragmentManager
                .beginTransaction()
                .hide(fragment)
                .commitAllowingStateLoss()
            return fragment as T
        }
        fragment = host.supportFragmentManager
            .fragmentFactory
            .instantiate(host.classLoader, fragmentClz.name)
        host.supportFragmentManager
            .beginTransaction()
            .hide(fragment)
            .commitAllowingStateLoss()
        return fragment as T
    }

    fun <T : Fragment?> showFragment(
        host: AppCompatActivity,
        containerId: Int,
        fragmentClz: Class<T>,
        data: Bundle?,
        needUpdateData: Boolean = false
    ): T {
        val fragmentTag = fragmentClz.name
        var fragment =
            host.supportFragmentManager.findFragmentByTag(fragmentTag)
        if (fragment != null) {
            if (needUpdateData) fragment.arguments = data
            host.supportFragmentManager
                .beginTransaction()
                .show(fragment)
                .commitAllowingStateLoss()
            return fragment as T
        }
        fragment = host.supportFragmentManager
            .fragmentFactory
            .instantiate(host.classLoader, fragmentClz.name)
        if (data != null) {
            fragment.arguments = data
        }
        return if (!fragment.isAdded) {
            addFragment(host, fragmentClz, containerId, data, needUpdateData)
        } else {
            host.supportFragmentManager
                .beginTransaction()
                .show(fragment)
                .commitAllowingStateLoss()
            fragment as T
        }
    }

}