package com.acitelight.aether.view.components

import android.app.Activity
import android.content.Context
import android.media.AudioManager
import android.view.View
import androidx.annotation.OptIn
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
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.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.VolumeUp
import androidx.compose.material.icons.filled.Brightness4
import androidx.compose.material.icons.filled.FastForward
import androidx.compose.material.icons.filled.Fullscreen
import androidx.compose.material.icons.filled.Pause
import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.ui.PlayerView
import com.acitelight.aether.view.pages.formatTime
import com.acitelight.aether.view.pages.moveBrit
import com.acitelight.aether.viewModel.VideoPlayerViewModel
import kotlin.math.abs


@OptIn(UnstableApi::class)
@Composable
fun PortalCorePlayer(modifier: Modifier, videoPlayerViewModel: VideoPlayerViewModel, cover: Float) {
    val exoPlayer: ExoPlayer = videoPlayerViewModel.player!!
    val context = LocalContext.current
    val activity = (context as? Activity)!!

    val audioManager = remember { context.getSystemService(Context.AUDIO_SERVICE) as AudioManager }
    val maxVolume = remember { audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC) }
    var volFactor by remember {
        mutableFloatStateOf(
            audioManager.getStreamVolume(AudioManager.STREAM_MUSIC).toFloat() / maxVolume.toFloat()
        )
    }

    fun setVolume(value: Int) {
        audioManager.setStreamVolume(
            AudioManager.STREAM_MUSIC,
            value.coerceIn(0, maxVolume),
            AudioManager.FLAG_PLAY_SOUND
        )
    }

    Box(modifier)
    {
        AndroidView(
            factory = {
                PlayerView(
                    it
                ).apply {
                    player = exoPlayer
                    useController = false
                    subtitleView?.let { sv ->
                        sv.visibility = View.GONE
                    }
                }
            },
            modifier = Modifier
                .align(Alignment.TopCenter)
                .fillMaxWidth()
                .pointerInput(Unit) {
                    detectDragGestures(
                        onDragStart = { offset ->
                            if (videoPlayerViewModel.locked) return@detectDragGestures
                            if (offset.x < size.width / 2) {
                                videoPlayerViewModel.draggingPurpose = -1
                            } else {
                                videoPlayerViewModel.draggingPurpose = -2
                            }
                        },
                        onDragEnd = {
                            if (videoPlayerViewModel.isPlaying && videoPlayerViewModel.draggingPurpose == 0)
                                exoPlayer.play()

                            videoPlayerViewModel.draggingPurpose = -1
                        },
                        onDrag = { change, dragAmount ->
                            if (videoPlayerViewModel.locked) return@detectDragGestures
                            if (abs(dragAmount.x) > abs(dragAmount.y) &&
                                (videoPlayerViewModel.draggingPurpose == -1 || videoPlayerViewModel.draggingPurpose == -2)
                            ) {
                                videoPlayerViewModel.draggingPurpose = 0
                                videoPlayerViewModel.planeVisibility = true
                                exoPlayer.pause()
                            } else if (videoPlayerViewModel.draggingPurpose == -1) videoPlayerViewModel.draggingPurpose =
                                1
                            else if (videoPlayerViewModel.draggingPurpose == -2) videoPlayerViewModel.draggingPurpose =
                                2

                            if (videoPlayerViewModel.draggingPurpose == 0) {
                                exoPlayer.seekTo((exoPlayer.currentPosition + dragAmount.x * 200.0f).toLong())
                                videoPlayerViewModel.playProcess =
                                    exoPlayer.currentPosition.toFloat() / exoPlayer.duration.toFloat()
                            } else if (videoPlayerViewModel.draggingPurpose == 2) {
                                val cu = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
                                volFactor = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
                                    .toFloat() / maxVolume.toFloat()
                                if (dragAmount.y < 0)
                                    setVolume(cu + 1)
                                else if (dragAmount.y > 0)
                                    setVolume(cu - 1)
                            } else if (videoPlayerViewModel.draggingPurpose == 1) {
                                moveBrit(dragAmount.y, activity, videoPlayerViewModel)
                            }

                        }
                    )
                }
                .pointerInput(Unit) {
                    detectTapGestures(
                        onDoubleTap = {
                            if (videoPlayerViewModel.locked) return@detectTapGestures
                            videoPlayerViewModel.isPlaying = !videoPlayerViewModel.isPlaying
                            if (videoPlayerViewModel.isPlaying) exoPlayer.play() else exoPlayer.pause()
                        },
                        onTap = {
                            if (videoPlayerViewModel.locked) return@detectTapGestures
                            videoPlayerViewModel.planeVisibility =
                                !videoPlayerViewModel.planeVisibility
                        },
                        onLongPress = {
                            if (videoPlayerViewModel.locked) return@detectTapGestures
                            videoPlayerViewModel.isLongPressing = true
                            exoPlayer.playbackParameters = exoPlayer.playbackParameters
                                .withSpeed(3.0f)
                        },
                        onPress = { offset ->
                            val pressResult = tryAwaitRelease()
                            if (pressResult && videoPlayerViewModel.isLongPressing) {
                                videoPlayerViewModel.isLongPressing = false
                                exoPlayer.playbackParameters = exoPlayer.playbackParameters
                                    .withSpeed(1.0f)
                            }
                        },
                    )
                }
        )

        AnimatedVisibility(
            visible = videoPlayerViewModel.isLongPressing,
            enter = slideInVertically(initialOffsetY = { fullHeight -> -fullHeight }),
            exit = slideOutVertically(targetOffsetY = { fullHeight -> -fullHeight }),
            modifier = Modifier
                .align(Alignment.TopCenter)
        )
        {
            Box(
                modifier = Modifier
                    .align(Alignment.TopCenter)
                    .padding(top = 24.dp)
                    .background(Color(0x44000000), RoundedCornerShape(18))
            )
            {
                Row {
                    Icon(
                        imageVector = Icons.Filled.FastForward,
                        contentDescription = "Fast Forward",
                        tint = Color.White,
                        modifier = Modifier
                            .size(36.dp)
                            .padding(4.dp)
                            .align(Alignment.CenterVertically)
                    )

                    Text(
                        text = "3X Speed...",
                        modifier = Modifier
                            .padding(4.dp)
                            .align(Alignment.CenterVertically),
                        fontSize = 16.sp,
                        fontWeight = FontWeight.Bold,
                        color = Color(0xFFFFFFFF)
                    )
                }
            }
        }

        AnimatedVisibility(
            visible = videoPlayerViewModel.draggingPurpose == 0,
            enter = fadeIn(
                initialAlpha = 0f,
            ),
            exit = fadeOut(
                targetAlpha = 0f
            ),
            modifier = Modifier.align(Alignment.Center)
        )
        {
            Text(
                text = "${formatTime((exoPlayer.duration * videoPlayerViewModel.playProcess).toLong())}/${
                    formatTime(
                        (exoPlayer.duration)
                    )
                }",
                fontWeight = FontWeight.Bold,
                modifier = Modifier.padding(bottom = 12.dp),
                fontSize = 18.sp
            )
        }

        AnimatedVisibility(
            visible = videoPlayerViewModel.draggingPurpose == 2,
            enter = fadeIn(
                initialAlpha = 0f,
            ),
            exit = fadeOut(
                targetAlpha = 0f
            ),
            modifier = Modifier.align(Alignment.Center)
        )
        {
            Row(Modifier
                .background(Color(0x88000000), RoundedCornerShape(18))
                .width(200.dp))
            {
                Icon(
                    imageVector = Icons.AutoMirrored.Filled.VolumeUp,
                    contentDescription = "Vol",
                    tint = Color.White,
                    modifier = Modifier
                        .size(48.dp)
                        .padding(8.dp)
                        .align(Alignment.CenterVertically)
                )
                BiliMiniSlider(
                    value = volFactor,
                    onValueChange = {},
                    modifier = Modifier
                        .height(4.dp)
                        .padding(horizontal = 8.dp)
                        .align(Alignment.CenterVertically)
                )
            }
        }

        AnimatedVisibility(
            visible = videoPlayerViewModel.draggingPurpose == 1,
            enter = fadeIn(
                initialAlpha = 0f,
            ),
            exit = fadeOut(
                targetAlpha = 0f
            ),
            modifier = Modifier.align(Alignment.Center)
        )
        {
            Row(Modifier
                .background(Color(0x88000000), RoundedCornerShape(18))
                .width(200.dp))
            {
                Icon(
                    imageVector = Icons.Default.Brightness4,
                    contentDescription = "Brightness",
                    tint = Color.White,
                    modifier = Modifier
                        .size(48.dp)
                        .padding(8.dp)
                        .align(Alignment.CenterVertically)
                )
                BiliMiniSlider(
                    value = videoPlayerViewModel.brit,
                    onValueChange = {},
                    modifier = Modifier
                        .height(4.dp)
                        .padding(horizontal = 8.dp)
                        .align(Alignment.CenterVertically)
                )
            }
        }

        if (cover > 0.0f)
            Spacer(Modifier
                .background(MaterialTheme.colorScheme.primary.copy(cover))
                .fillMaxSize())

        AnimatedVisibility(
            visible = (!videoPlayerViewModel.planeVisibility) || videoPlayerViewModel.locked,
            enter = fadeIn(
                initialAlpha = 0f,
            ),
            exit = fadeOut(
                targetAlpha = 0f
            ),
            modifier = Modifier
                .fillMaxWidth()
                .align(Alignment.BottomCenter)
        ) {
            BiliMiniSlider(
                value = videoPlayerViewModel.playProcess,
                onValueChange = {},
                modifier = Modifier
                    .height(4.dp)
                    .align(Alignment.BottomCenter)
            )
        }

        AnimatedVisibility(
            visible = videoPlayerViewModel.planeVisibility && (!videoPlayerViewModel.locked),
            enter = fadeIn(
                initialAlpha = 0f,
            ),
            exit = fadeOut(
                targetAlpha = 0f
            ),
            modifier = Modifier
                .fillMaxWidth()
                .align(Alignment.BottomCenter)
                .height(42.dp)
        )
        {
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .align(Alignment.BottomCenter)
                    .background(
                        brush = Brush.verticalGradient(
                            colors = listOf(
                                Color.Transparent,
                                Color.Black.copy(alpha = 0.4f),
                            )
                        )
                    ),
                horizontalArrangement = Arrangement.SpaceBetween,
            ) {
                IconButton(
                    onClick = {
                        videoPlayerViewModel.isPlaying = !videoPlayerViewModel.isPlaying
                        if (videoPlayerViewModel.isPlaying) exoPlayer.play() else exoPlayer.pause()
                    },
                    Modifier
                        .size(36.dp)
                        .align(Alignment.CenterVertically)
                ) {
                    Icon(
                        imageVector = if (videoPlayerViewModel.isPlaying) Icons.Default.Pause else Icons.Default.PlayArrow,
                        contentDescription = "Play/Pause",
                        tint = Color.White,
                        modifier = Modifier.size(32.dp)
                    )
                }

                BiliStyleSlider(
                    value = videoPlayerViewModel.playProcess,
                    onValueChange = { value ->
                        exoPlayer.seekTo((exoPlayer.duration * value).toLong())
                    },
                    modifier = Modifier
                        .height(8.dp)
                        .align(Alignment.CenterVertically)
                        .weight(1f)
                )

                Text(
                    text = formatTime((exoPlayer.duration * videoPlayerViewModel.playProcess).toLong()),
                    maxLines = 1,
                    fontSize = 12.sp,
                    color = Color(0xFFFFFFFF),
                    fontWeight = FontWeight.Bold,
                    modifier = Modifier
                        .width(80.dp)
                        .align(Alignment.CenterVertically)
                        .padding(start = 12.dp)
                )

                IconButton(
                    onClick = {
                        videoPlayerViewModel.isLandscape = true
                    },
                    Modifier
                        .size(36.dp)
                        .align(Alignment.CenterVertically)
                ) {
                    Icon(
                        Icons.Default.Fullscreen,
                        contentDescription = "FullScreen",
                        tint = Color.White,
                        modifier = Modifier.size(32.dp)
                    )
                }
            }
        }

        SubtitleOverlay(
            cues = videoPlayerViewModel.cues,
            modifier = Modifier.matchParentSize()
        )
    }
}

