package com.pixelized.desktop.lwa.ui.navigation.window

import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.key
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.WindowState
import androidx.compose.ui.window.rememberWindowState
import com.pixelized.desktop.lwa.ui.composable.key.KeyEventHandler
import com.pixelized.desktop.lwa.ui.composable.key.LocalKeyEventHandlers
import com.pixelized.desktop.lwa.ui.navigation.window.destination.Window
import java.awt.Toolkit

val LocalWindow = compositionLocalOf<Window> {
    error("Local Window is not yet ready")
}
val LocalWindowState = compositionLocalOf<WindowState> {
    error("Local Window state is not yet ready")
}

@Stable
class WindowController(
    val maxWindowHeight: Dp,
) {
    private val _windows = mutableStateOf<Map<String, Window>>(emptyMap())
    val windows: State<Map<String, Window>> get() = _windows

    fun openWindow(window: Window) {
        _windows.value = _windows.value.toMutableMap().apply { this[window.id] = window }
    }

    fun hideWindow(window: Window) {
        hideWindow(id = window.id)
    }

    fun hideWindow(id: String) {
        _windows.value = _windows.value.toMutableMap().apply { this.remove(id) }
    }
}

@Composable
@Stable
fun rememberMaxWindowHeight(): Dp {
    val density = LocalDensity.current
    val maxWindowHeight = remember(density) {
        val screenSize = Toolkit.getDefaultToolkit().screenSize
        val screenHeight = screenSize.height
        with(density) { screenHeight.toDp() - 128.dp }
    }
    return maxWindowHeight
}

@Composable
fun WindowsNavHost(
    controller: WindowController,
    content: @Composable (Window) -> Unit,
) {
    controller.windows.value.forEach { (id, window) ->
        key(id) {
            val state = rememberWindowState(size = window.size)
            val keyEventHandlers = remember { mutableStateListOf<KeyEventHandler>() }

            CompositionLocalProvider(
                LocalWindow provides window,
                LocalWindowState provides state,
                LocalKeyEventHandlers provides keyEventHandlers,
            ) {
                Window(
                    onCloseRequest = { controller.hideWindow(id = window.id) },
                    state = state,
                    title = window.title,
                    onKeyEvent = { event ->
                        keyEventHandlers.reversed().any { it(event) }
                    },
                ) {
                    content.invoke(window)
                }
            }
        }
    }
}