package de.sebse.fuplanner2

import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.selection.selectable
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Menu
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import androidx.navigation.NavOptions
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.rememberNavController
import de.sebse.fuplanner2.ui.theme.AppTheme
import kotlinx.coroutines.launch


abstract class NavLinks(
    @StringRes val title: Int,
    @DrawableRes val drawable: Int,
    val route: String
)

@Composable
fun DrawerLayout(
    appName: String,
    menu: List<NavLinks>,
    startDestination: String,
    builder: NavGraphBuilder.(Tools) -> Unit
) {
    val scaffoldState = rememberScaffoldState(rememberDrawerState(DrawerValue.Closed))
    val scope = rememberCoroutineScope()
    val navController = rememberNavController()
    val (title, setTitle) = remember {
        mutableStateOf(appName)
    }
    val tools = Tools(setTitle = { setTitle(it) }, navController)
    Scaffold(
        scaffoldState = scaffoldState,
        topBar = {
            TopBar(title = title) {
                scope.launch {
                    scaffoldState.drawerState.open()
                }
            }
        },
        drawerContent = {
            Drawer(currentRoute = navController.currentDestination?.route, menu = menu) {
                scope.launch { scaffoldState.drawerState.close() }
                navController.navigate(it)
            }
        },
    ) {
        NavHost(navController, startDestination = startDestination) {
            this.apply { builder(tools) }
        }
    }
}

class Tools(val setTitle: (String) -> Unit, private val navController: NavHostController) {
    private val navOptions = NavOptions.Builder()
        .setEnterAnim(R.anim.slide_in_right)
        .setExitAnim(R.anim.slide_out_left)
        .setPopEnterAnim(R.anim.slide_in_left)
        .setPopExitAnim(R.anim.slide_out_right)
        .build();

    fun navBack() {
        this.navController.popBackStack()
    }

    fun navTo(route: String) {
        this.navController.navigate(route, navOptions = navOptions)
    }
}

@Composable
fun TopBar(title: String = "", onOpenClick: () -> Unit) {
    TopAppBar(
        title = {
            Text(
                text = title
            )
        },
        navigationIcon = {
            IconButton(onClick = onOpenClick) {
                Icon(Icons.Filled.Menu, "")
            }
        }
    )
}

@Composable
fun Drawer(currentRoute: String?, menu: List<NavLinks>, onItemClick: (route: String) -> Unit) {
    Column(
        Modifier
            .widthIn(min = 300.dp, max = 500.dp)
            .fillMaxHeight()
    ) {
        Icon(
            painter = painterResource(R.drawable.ic_logo_mono),
            contentDescription = "App icon"
        )
        DrawerItems(currentRoute, menu = menu, onItemClick)
    }
}

@Composable
fun DrawerItems(currentRoute: String?, menu: List<NavLinks>, onItemClick: (route: String) -> Unit) {
    menu.forEach { screen ->
        val isSelected = currentRoute == screen.route
        val modifier = Modifier
            .padding(top = 24.dp)
            .selectable(isSelected) { onItemClick(screen.route) }
        Row(
            modifier = modifier
        ) {
            Icon(
                painter = painterResource(screen.drawable),
                contentDescription = stringResource(screen.title)
            )
            Text(
                text = stringResource(screen.title),
                style = MaterialTheme.typography.h6
            )
        }
    }
}

@Preview
@Composable
fun TopBarPreview() {
    AppTheme {
        TopBar(
            title = "A title"
        ) { }
    }
}

@Preview
@Composable
fun DrawerPreview() {
    AppTheme {
        Drawer(currentRoute = "courses", menu = screens) { }
    }
}
