package com.isidroid.core.ext

import android.annotation.SuppressLint
import androidx.core.net.toUri
import androidx.navigation.NavController
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavHostController
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.onEach
import timber.log.Timber

fun NavController.navigateSingleTopTo(
    route: String,
    dropCurrent: Boolean = true,
    isSaveState: Boolean? = null,
    isLaunchSingleTop: Boolean = true,
    isRestoreState: Boolean? = null,
    isInclusive: Boolean = true,
    popupToRoute: String? = null
) {
    val dropNode = if (dropCurrent) currentDestination?.route else popupToRoute
    val node = dropNode?.let { graph.findNode(dropNode) } ?: graph.findStartDestination()

    navigate(route) {
        popUpTo(node.id) {
            inclusive = isInclusive
            if (isSaveState != null)
                saveState = isSaveState
        }

        isLaunchSingleTop.also { launchSingleTop = it }
        isRestoreState?.also { restoreState = it }
    }
}


/**
 * Just for printing route paths. Need to be used in LaunchedEffect as follows
 *
 *  LaunchedEffect(Unit) { navController.printCurrentDestination() }
 */
suspend fun NavHostController?.printCurrentDestination(
    tag: String = "navigation_graph",
    printFullDebug: Boolean = false
) {
    this ?: return

    visibleEntries.onEach { entry ->
        val message = entry.mapNotNull {
            val route = it.destination.route

            if (route == null)
                null
            else
                buildString {
                    append(route.let { s ->
                        if (printFullDebug)
                            s
                        else {
                            val index = s.indexOf("?")
                            if (index > 0) s.take(index) else s
                        }
                    })

//                    if (it.arguments != null && it.arguments?.isEmpty != true)
//                        append(": ")
//                            .append("arguments=${it.arguments.debug}")
                }
        }


        Timber.tag(tag).i("$message")
    }.collect()
}

@SuppressLint("RestrictedApi")
suspend fun NavHostController.printNavigationStack(tag: String = "navigation_graph") {
    currentBackStack.collect { list ->
        val backstack = list.mapNotNull { navBackStackEntry -> navBackStackEntry.destination.route?.toUri()?.path }.joinToString()
        Timber.tag(tag).i(backstack)
    }
}