package com.laseroptek.raman.ui

import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.content.res.Resources
import android.media.AudioManager
import android.os.Build
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.annotation.RequiresApi
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.navigation.compose.rememberNavController
import com.laseroptek.raman.const.CMD
import com.laseroptek.raman.const.LASER_STATUS
import com.laseroptek.raman.const.READ_WRITE
import com.laseroptek.raman.ui.screens.main.MainScreen
import com.laseroptek.raman.ui.screens.main.MainViewModel
import com.laseroptek.raman.ui.theme.LightColors
import com.laseroptek.raman.ui.theme.MainTheme
import com.laseroptek.raman.utils.SharedPreferenceHelper
import com.laseroptek.raman.utils.SystemSound.setCurrentSystemVolume
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import timber.log.Timber
import java.util.Locale

@AndroidEntryPoint
class MainActivity : ComponentActivity() {

    ////////////////////////////////////////////////////////////////////////////////////////////////
    // private val

    /** mainViewModel - MainActivity ViewModel
     * - 모든 Screen/View에서 공통으로 사용하는 ViewModel
     * - Preference 초기 값 설정.
     * - Serial 수신 및 수신 데이터 처리.
     * - Serial 송신.
     */
    private val mainViewModel: MainViewModel by viewModels()


    /** selectApkLauncher - ActivityResultLauncher for selecting APK file.
     * - apk 설치 파일 선택 및 설치
     */
    //var selectedApkUri: Uri? = null
    private val selectApkLauncher: ActivityResultLauncher<Intent> =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            // This callback is executed when the file chooser is closed.
            // Reliably hide the system navigation bar to restore the app's immersive state.
            setSystemBarsVisible(false)

            if (result.resultCode == RESULT_OK) {
                result.data?.data?.let { uri ->
                    //selectedApkUri = uri
                    Timber.d("Selected APK URI: $uri")
                }
            } else {
                Timber.d("No APK file selected")
                //selectedApkUri = null
            }
        }


    ////////////////////////////////////////////////////////////////////////////////////////////////
    // override functions

    /** attachBaseContext - language setting
     * - onCreate() 이전에 호출 됨
     * - Locale 및 Resouce 반영
     */
    override fun attachBaseContext(newBase: Context) {
        val selectedLanguage = SharedPreferenceHelper.getString(newBase, "language", "en") ?: "en"
        Timber.d("attachBaseContext: language: ${selectedLanguage}")

        val locale = Locale.forLanguageTag(selectedLanguage)
        Locale.setDefault(locale) // Set default locale for the app

        val config = Configuration(newBase.resources.configuration)
        config.setLocale(locale)
        val localizedContext = newBase.createConfigurationContext(config)
        super.attachBaseContext(localizedContext)
    }

    fun setSystemBarsVisible(visible: Boolean) {
        val windowInsetsController = WindowCompat.getInsetsController(window, window.decorView)
        if (visible) {
            // Makes the bars visible and pushes your app content down.
            WindowCompat.setDecorFitsSystemWindows(window, true)
            windowInsetsController.show(WindowInsetsCompat.Type.systemBars())
        } else {
            // Allows your app content to draw behind the bars (edge-to-edge).
            WindowCompat.setDecorFitsSystemWindows(window, false)
            windowInsetsController.systemBarsBehavior =
                WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
            // Hides the bars, making them transparent.
            windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
        }
    }

    @RequiresApi(Build.VERSION_CODES.R)
    @OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setSystemBarsVisible(false)

        enableEdgeToEdge()

        // hide soft keyboard (not working)
        //window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN)

        // Set Full Screen (Immersive Mode)
        /*
        val windowInsetsController = WindowCompat.getInsetsController(window, window.decorView)
        windowInsetsController.apply {
            systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
            hide(WindowInsetsCompat.Type.statusBars())
            hide(WindowInsetsCompat.Type.navigationBars())
            hide(WindowInsetsCompat.Type.systemBars())
            //hide(WindowInsetsCompat.Type.ime()) // hide soft keyboard (not working)
        }
        */

        /*
        window.attributes.layoutInDisplayCutoutMode =
            WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES

        WindowCompat.setDecorFitsSystemWindows(window, true)

        val windowInsetsController = WindowCompat.getInsetsController(window, window.decorView)
        windowInsetsController.show(WindowInsetsCompat.Type.systemBars())
        */


        initialize()

        // apk observeUpdateEvents
        observeUpdateEvents()

        setContent {
            rememberNavController()
            val mainNavController = rememberNavController()

            //추후 동적으로 테마 변경 요청시 고려.
            //var isDarkTheme by remember { mutableStateOf(false) } // Initial theme state

            MainTheme(
                colorScheme = LightColors // DarkColors
            ) {
                /*
                SplashNavGraph(
                    splashNavController = splashNavController,
                    mainNavController = mainNavController,
                    mainViewModel = mainViewModel,
                )
                */

                MainScreen(
                    mainNavController,
                    mainViewModel
                )
            }
        }
    }

    override fun onPause() {
        super.onPause()
        Timber.d("onPause")

        // set laser status (false)
        mainViewModel.txPacket(READ_WRITE.WRITE, CMD.LASER_STATUS, byteArrayOf(LASER_STATUS.STAND_BY.toByte()))
    }

    override fun onDestroy() {
        super.onDestroy()
        Timber.d("onDestroy")

        // - not used
        //unregisterReceiver(usbReceiver)
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////
    // private functions

    /** observeUpdateEvents - apkUpdateEvent monitoring
     * - Engineer Mode에서 Update 시 발생시킨 Event 모니터
     */
    private fun observeUpdateEvents() {
        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                mainViewModel.apkUpdateEvent.collect {
                    Timber.d("apkUpdateEvent received")

                    // Before launching the system file chooser, show the navigation bar.
                    setSystemBarsVisible(true)

                    val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
                        addCategory(Intent.CATEGORY_OPENABLE)
                        type = "application/vnd.android.package-archive" // MIME type for APK files
                    }
                    selectApkLauncher.launch(intent)
                }
            }
        }
    }

    // not working
    /*
    private fun setAppLocale(languageCode: String) { // e.g., "es", "fr-CA"
        val appLocale: LocaleListCompat = LocaleListCompat.forLanguageTags(languageCode)
        AppCompatDelegate.setApplicationLocales(appLocale)
        // No need to manually call recreate() usually, AppCompat handles it.
    }
    */

    private fun initialize() {
        // Force VM creation on Main thread (instantly)
        val vm = mainViewModel

        // Timber.d("density: ${Resources.getSystem().displayMetrics.density}")

        // Use Dispatchers.Default for orchestration to keep IO free for disk
        lifecycleScope.launch(Dispatchers.IO) {
            try {
                // 1. Heavy background work
                vm.performFullInitialization()

                withContext(Dispatchers.Main) {
                    // 2. STAGGERED START:
                    // Let the Main Thread draw the Loading screen one last time
                    delay(200)

                    // 3. Sync Volume (this can be slow, do it before flipping the UI)
                    setCurrentSystemVolume(
                        applicationContext,
                        AudioManager.STREAM_MUSIC,
                        vm.sliderVolume.value.toInt()
                    )

                    // 4. IMPORTANT: Signal initialization
                    vm.setInitialized(true)

                    // 5. POST-RENDER DELAY:
                    // Wait for the Dashboard to actually draw before starting Serial Loops.
                    // This prevents serial interrupts from stealing CPU during the first frame.
                    delay(200)

                    vm.txPacketOnce()

                    vm.rxPacketLoop()
                    vm.txPacketLoop()

                    Timber.d("System fully operational.")
                }
            } catch (e: Exception) {
                Timber.e(e)
            }
        }
    }

    // End of File
    ////////////////////////////////////////////////////////////////////////////////////////////////

}
