package net.helcel.beans.activity.sub


import android.content.Context
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.CheckboxDefaults
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Tab
import androidx.compose.material.TabRow
import androidx.compose.material.Text
import androidx.compose.material.TriStateCheckbox
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.state.ToggleableState
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import net.helcel.beans.countries.GeoLoc
import net.helcel.beans.countries.Group
import net.helcel.beans.countries.World
import net.helcel.beans.helper.AUTO_GROUP
import net.helcel.beans.helper.Data
import net.helcel.beans.helper.NO_GROUP
import net.helcel.beans.helper.Settings
import kotlin.math.min

@Preview
@Composable
fun EditPlaceScreenPreview(){
    EditPlaceScreen(Group.EEE)
}

/**
 * Applies a place straight away where a single group makes the choice obvious,
 * as tapping the checkbox does. Returns false when the group still has to be
 * picked from the colour dialog.
 */
fun applyDirectVisit(ctx: Context, loc: GeoLoc): Boolean {
    Data.selected_geoloc = loc
    Data.selected_group = null
    if (Data.groups.size() != 1 || !Settings.isSingleGroup(ctx)) return false
    val current = Data.visits.getVisited(loc)
    Data.visits.setVisited(
        loc,
        if (current == NO_GROUP || current == AUTO_GROUP) Data.groups.getUniqueEntry()!!.key
        else if (loc.children.any { Data.visits.getVisited(it) != NO_GROUP }) AUTO_GROUP
        else NO_GROUP,
    )
    syncVisited()
    Data.saveData()
    Data.selected_geoloc = null
    return true
}

/** Stores whatever the colour dialog came back with. */
fun commitVisitDialog(cleared: Boolean) {
    if (cleared) {
        Data.visits.setVisited(Data.selected_geoloc, NO_GROUP)
        syncVisited()
        Data.saveData()
    }
    if (Data.selected_group != null && Data.selected_geoloc != null) {
        Data.visits.setVisited(Data.selected_geoloc, Data.selected_group!!.key)
        syncVisited()
        Data.saveData()
    }
    Data.selected_geoloc = null
    Data.selected_group = null
}

fun syncVisited(loc: GeoLoc?=World.WWW): Boolean {
    var changed = false
    loc?.children?.forEach { tt ->
        tt.children.forEach {itc->
            if(Data.visits.getVisited(itc) in listOf(AUTO_GROUP,NO_GROUP)) {
                val newState = if(itc.children.any { c -> Data.visits.getVisited(c) != NO_GROUP })
                    AUTO_GROUP
                else
                    NO_GROUP

                if (Data.visits.getVisited(itc) != newState) {
                    Data.visits.setVisited(itc, newState)
                    changed = true
                }
            }
        }
        if(Data.visits.getVisited(tt) in listOf(AUTO_GROUP,NO_GROUP)) {
            val newState = if(tt.children.any { itc -> Data.visits.getVisited(itc) != NO_GROUP })
                AUTO_GROUP
            else
                NO_GROUP

            if (Data.visits.getVisited(tt) != newState) {
                Data.visits.setVisited(tt, newState)
                changed = true
            }
        }
    }
    // Sync World from Continents
    if (loc != null && Data.visits.getVisited(loc) in listOf(AUTO_GROUP, NO_GROUP)) {
        val newState = if(loc.children.any { Data.visits.getVisited(it) != NO_GROUP })
            AUTO_GROUP
        else
            NO_GROUP
        if (Data.visits.getVisited(loc) != newState) {
            Data.visits.setVisited(loc, newState)
            changed = true
        }
    }
    return changed
}

@Composable
fun EditPlaceScreen(loc: GeoLoc, onExit:()->Unit={}) {
    val visits by Data.visits.visitsFlow.collectAsState()
    var showEdit by remember { mutableStateOf(false) }
    val tabs : SnapshotStateList<GeoLoc> = remember { mutableStateListOf(loc) }
    val ctx = LocalContext.current
    var selectedTab by remember { mutableIntStateOf(0) }

    LaunchedEffect(tabs.size) {
        selectedTab = tabs.lastIndex
    }
    SideEffect {
        // visits is used to trigger sync whenever data changes
        if (visits.isNotEmpty() || true) {
            if (syncVisited()) {
                Data.saveData()
            }
        }
    }
    BackHandler {
        if (tabs.size > 1) tabs.removeAt(tabs.lastIndex)
        else onExit()
    }
    if(showEdit)
        EditPlaceDialog(false) {
            showEdit = false
            commitVisitDialog(it)
        }

    Column {
        val currentTab = tabs.getOrNull(selectedTab) ?: return@Column
        TabRow(
            selectedTabIndex = min(tabs.lastIndex, selectedTab),
        ) {
            tabs.forEachIndexed { index, tab ->
                Tab(
                    selected = selectedTab == index,
                    onClick = {
                        while (tabs.size > index + 1)
                            tabs.removeAt(tabs.lastIndex)
                    },
                    text = { Text(tab.fullName) }
                )
            }
        }

        LazyColumn(
            modifier = Modifier.fillMaxSize()
        ) {
            items(currentTab.children.toList(), key= {it.code}) { loc ->

                GeoLocRow(loc, {
                        if (loc.children.isNotEmpty()){
                            tabs.add(loc)
                        }
                    }, {
                        if (!applyDirectVisit(ctx, loc)) showEdit = true
                    })

            }
        }

    }
}


@Composable
fun GeoLocRow(
    loc: GeoLoc,
    onClick: () -> Unit,
    onToggle: () -> Unit,
) {
    val visits by Data.visits.visitsFlow.collectAsState()
    val checked by remember(visits, loc) {
        derivedStateOf {
            when (visits.getOrElse(loc.code) { NO_GROUP }) {
                NO_GROUP -> ToggleableState.Off
                AUTO_GROUP -> ToggleableState.Indeterminate
                else -> ToggleableState.On
            }
        }
    }

    val color = if (Data.visits.getVisited(loc) !in listOf(NO_GROUP, AUTO_GROUP))
        Color(Data.groups.getGroupFromKey(Data.visits.getVisited(loc)).color.color)
    else MaterialTheme.colors.onBackground
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .height(50.dp)
            .clickable(onClick = onClick) // whole row clickable
            .padding(horizontal = 20.dp, vertical = 4.dp),
        verticalAlignment = Alignment.CenterVertically
    ) {
        Text(
            text = loc.fullName,
            style = MaterialTheme.typography.body2,
            color = MaterialTheme.colors.onBackground,
            modifier = Modifier.weight(1f)
        )

        Text(
            text = "",//loc.children.size.toString(),
            style = MaterialTheme.typography.body2,
            modifier = Modifier.padding(end = 16.dp)
        )

        TriStateCheckbox(
            state = checked,
            onClick = onToggle,
            colors = CheckboxDefaults.colors(
                checkedColor = color,
            ),

            modifier = Modifier.size(24.dp)
        )
    }
    Spacer(modifier = Modifier
        .height(2.dp)
        .fillMaxWidth()
        .background(MaterialTheme.colors.onBackground))
}