package de.jadehs.strassenschadenpro2.pages

import android.Manifest
import android.content.Context
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
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.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.itemsIndexed
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp
import com.arcgismaps.geometry.Point
import com.arcgismaps.geometry.SpatialReference
import com.arcgismaps.location.LocationDisplayAutoPanMode
import com.arcgismaps.toolkit.geoviewcompose.MapView
import com.arcgismaps.toolkit.geoviewcompose.rememberLocationDisplay
import com.google.android.gms.location.LocationServices
import de.jadehs.strassenschadenpro2.AlbumViewModel
import de.jadehs.strassenschadenpro2.MapViewModel
import de.jadehs.strassenschadenpro2.components.DropDownMenuBox
import de.jadehs.strassenschadenpro2.components.album.AlbumViewState
import de.jadehs.strassenschadenpro2.components.album.Intent
import de.jadehs.strassenschadenpro2.components.album.PhotoData
import kotlinx.coroutines.launch

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CreatePage(modifier: Modifier = Modifier, mapViewModel: MapViewModel) {
    var beschreibungTextFieldValue = remember { mutableStateOf(TextFieldValue("")) }

    var currentDamageType = remember { mutableStateOf("")}

    var showModalBottomSheet = remember { mutableStateOf(false) }

    var enableSaveButton = remember { mutableStateOf(false) }

    val coroutineScope = rememberCoroutineScope()

    var albumViewModel = remember { AlbumViewModel(coroutineScope.coroutineContext) }

    val locationDisplay = rememberLocationDisplay().apply {
        setAutoPanMode(LocationDisplayAutoPanMode.Off)
    }

    val context = LocalContext.current

    if (checkPermissions(context)) {
        // Permissions are already granted.
        LaunchedEffect(Unit) {
            locationDisplay.dataSource.start()
        }
    } else {
        RequestPermissions(
            context = context,
            onPermissionsGranted = {
                coroutineScope.launch {
                    locationDisplay.dataSource.start()
                }
            }
        )
    }

    val fuesedLocationClient = remember { LocationServices.getFusedLocationProviderClient(context) }

    Column(modifier = modifier.fillMaxSize()
        .verticalScroll(rememberScrollState())
        .padding(top = 16.dp, start = 16.dp, end = 16.dp, bottom = 16.dp),
        verticalArrangement = Arrangement.Top,
        horizontalAlignment = Alignment.CenterHorizontally) {
        OutlinedTextField(
            modifier = Modifier.fillMaxWidth(),
            value = beschreibungTextFieldValue.value,
            onValueChange = {
                beschreibungTextFieldValue.value = it
                enableSaveButton.value = beschreibungTextFieldValue.value.text.isNotEmpty() && currentDamageType.value.isNotEmpty()
            },
            minLines = 5,
            label = { Text("Beschreibung")}
        )
        DropDownMenuBox(
            modifier = Modifier
                .padding(8.dp),
            textFieldLabel = "Select damage type",
            textFieldValue = currentDamageType.value,
            dropDownItemList = mapViewModel.damageTypeList,
            onIndexSelected = { index ->
                currentDamageType.value = mapViewModel.damageTypeList[index]
                enableSaveButton.value = beschreibungTextFieldValue.value.text.isNotEmpty() && currentDamageType.value.isNotEmpty()
            }
        )
        AlbumScreen(modifier= Modifier, viewModel = albumViewModel)
        Row(modifier = Modifier.fillMaxWidth(),
            horizontalArrangement = Arrangement.SpaceEvenly){
            Button(enabled = enableSaveButton.value,
                onClick = {
                    fuesedLocationClient.lastLocation.addOnSuccessListener { location ->
                        location?.let { location->
                            val beschreibung = beschreibungTextFieldValue.value.text
                            val typ = currentDamageType.value
                            var point = Point(location.longitude,
                                location.latitude,
                                SpatialReference.wgs84())
                            val photoDataList = getPhotosFromAlbum(context,albumViewModel)
                            mapViewModel.createFeatureWithAttributesAtPoint(
                                point,
                                beschreibung,
                                typ,
                                photoDataList)
                        }
                    }
                }){
                Text("GPS")
            }
            Button(enabled = enableSaveButton.value,
                onClick = {
                showModalBottomSheet.value = !showModalBottomSheet.value
            }){
                Text("Karte")
            }
        }
    }
    if(showModalBottomSheet.value) {
        ModalBottomSheet(
            sheetGesturesEnabled = false,
            onDismissRequest = {
                showModalBottomSheet.value = false
            }
        ) {
            MapView(
                modifier = Modifier,
                arcGISMap = mapViewModel.map,
                locationDisplay = locationDisplay,
                mapViewProxy = mapViewModel.mapViewProxy,
                onSingleTapConfirmed = { singleTapConfirmedEvent ->
                    val screenCoordinate = singleTapConfirmedEvent.screenCoordinate
                    val beschreibung = beschreibungTextFieldValue.value.text
                    val typ = currentDamageType.value
                    val photoDataList=getPhotosFromAlbum(context,albumViewModel)
                    mapViewModel.createFeatureWithAttributesAt(
                        screenCoordinate,
                        beschreibung,
                        typ,
                        photoDataList
                    )
                },
            )
        }
    }

}

@Composable
fun AlbumScreen(modifier: Modifier = Modifier, viewModel: AlbumViewModel) {
    // collecting the flow from the view model as a state allows our ViewModel and View
    // to be in sync with each other.
    val viewState: AlbumViewState by viewModel.viewStateFlow.collectAsState()

    val currentContext = LocalContext.current

    // launches photo picker
    val pickImageFromAlbumLauncher = rememberLauncherForActivityResult(ActivityResultContracts.PickMultipleVisualMedia()) { urls ->
        viewModel.onReceive(Intent.OnFinishPickingImagesWith(currentContext, urls))
    }

    // launches camera
    val cameraLauncher = rememberLauncherForActivityResult(ActivityResultContracts.TakePicture()) { isImageSaved ->
        if (isImageSaved) {
            viewModel.onReceive(Intent.OnImageSavedWith(currentContext))
        } else {
            // handle image saving error or cancellation
            viewModel.onReceive(Intent.OnImageSavingCanceled)
        }
    }

    // launches camera permissions
    val permissionLauncher = rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) { permissionGranted ->
        if (permissionGranted) {
            viewModel.onReceive(Intent.OnPermissionGrantedWith(currentContext))
        } else {
            // handle permission denied such as:
            viewModel.onReceive(Intent.OnPermissionDenied)
        }
    }

    // this ensures that the camera is launched only once when the url of the temp file changes
    LaunchedEffect(key1 = viewState.tempFileUrl) {
        viewState.tempFileUrl?.let {
            cameraLauncher.launch(it)
        }
    }

    // basic view that has 2 buttons and a grid for selected pictures
    Column(modifier = Modifier.padding(20.dp),
        horizontalAlignment = Alignment.CenterHorizontally) {
        Row {
            Button(onClick = {
                // get user's permission first to use camera
                permissionLauncher.launch(Manifest.permission.CAMERA)
            }) {
                Text(text = "Take a photo")
            }
            Spacer(modifier = Modifier.width(16.dp))
            Button(onClick = {
                // Image picker does not require special permissions and can be activated right away
                val mediaRequest = PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly)
                pickImageFromAlbumLauncher.launch(mediaRequest)
            }) {
                Text(text = "Pick a picture")
            }
        }
        Spacer(modifier = Modifier.height(16.dp))
        Text(text = "Selected Pictures")
        LazyVerticalGrid(modifier = Modifier.fillMaxWidth().heightIn(0.dp, 1200.dp),
            columns = GridCells.Adaptive(150.dp),
            userScrollEnabled = false) {
            itemsIndexed(viewState.selectedPictures) { index, picture ->
                Image(modifier = Modifier.padding(8.dp),
                    bitmap = picture,
                    contentDescription = null,
                    contentScale = ContentScale.FillWidth
                )
            }
        }
    }
}

fun getPhotosFromAlbum(context: Context,albumViewModel: AlbumViewModel): List<PhotoData>{
    var photoDataList = mutableListOf<PhotoData>()

    albumViewModel.viewStateFlow.value.imageUris.forEach { uri ->
        context.contentResolver.openInputStream(uri).use { inputStream ->
            try {
                val name = "image_${System.currentTimeMillis()}.png"
                val contentType = "image/png"
                val byteArray = inputStream?.readBytes()

                if (byteArray!=null) {
                    photoDataList.add(
                        PhotoData(
                            name,
                            contentType,
                            byteArray
                        )
                    )
                }
            }catch (e: Exception){

            }

        }

    }

    return photoDataList
}



















