package de.sebse.fuplanner2

import android.accounts.Account
import android.content.Intent
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.os.bundleOf
import androidx.lifecycle.*
import androidx.navigation.NavOptions
import androidx.navigation.findNavController
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import de.sebse.fuplanner2.auth.AppAccounts
import de.sebse.fuplanner2.database.AppDatabase
import de.sebse.fuplanner2.database.Course
import de.sebse.fuplanner2.database.User
import de.sebse.fuplanner2.databinding.ActivityMainBinding
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch


class MainActivity() : AppCompatActivity() {

    private lateinit var appBarConfiguration: AppBarConfiguration
    private lateinit var activityViewModel: MainActivityViewModel
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
        val navController = navHostFragment.navController
        binding = ActivityMainBinding.inflate(layoutInflater)
        setSupportActionBar(binding.appBarMain.toolbar)

        activityViewModel = ViewModelProvider(this).get(MainActivityViewModel::class.java)

        activityViewModel.user.observe(this) {
            binding.navView.getHeaderView(0).run {
                findViewById<TextView>(R.id.nav_header_title).text = getString(R.string.full_name, it?.firstName, it?.lastName)
                findViewById<TextView>(R.id.nav_header_subtitle).text = it?.email
            }
        }
        activityViewModel.notificationCnt.observe(this) {
            binding.navView.menu.findItem(R.id.nav_notifications).apply {
                icon = ContextCompat.getDrawable(
                    this@MainActivity,
                    if (it == 0) R.drawable.ic_menu_notifications_none else R.drawable.ic_menu_notifications
                )
                actionView = if (it == 0)
                    null
                else layoutInflater.inflate(R.layout.nav_action_view_counter, binding.navView, false).apply {
                    findViewById<TextView>(R.id.counterText).text = when (it) {
                        in 0..99 -> it.toString()
                        else -> "99+"
                    }
                }
            }
        }
        activityViewModel.latestSemester.observe(this) {
            val courseOrder = binding.navView.menu.findItem(R.id.nav_courses).order
            var i = binding.navView.menu.size() - 1
            while(i >= 0) {
                val menuItem: MenuItem = binding.navView.menu.getItem(i--)
                if (menuItem.order / 100 == courseOrder / 100 && menuItem.order != courseOrder) {
                    binding.navView.menu.removeItem(menuItem.itemId)
                }
            }
            it.mapIndexed { index, course ->
                val itemOrder = courseOrder / 100 * 100 + index + 2
                binding.navView.menu.add(0, itemOrder, itemOrder, course.title).setOnMenuItemClickListener {
                    navController.navigate(
                        R.id.course_details,
                        bundleOf("courseId" to course.uid, "title" to course.title),
                        NavOptions.Builder().setPopUpTo(R.id.nav_courses, false).build()
                    )
                    binding.drawerLayout.closeDrawers()
                    false
                }
            }
        }

        appBarConfiguration = AppBarConfiguration(
            setOf(R.id.nav_courses, R.id.nav_canteen, R.id.nav_schedule, R.id.nav_notifications),
            binding.drawerLayout
        )
        setupActionBarWithNavController(navController, appBarConfiguration)
        binding.navView.setupWithNavController(navController)

        if (intent.getBooleanExtra(EXTRA_OPEN_NOTIFICATIONS, false)) {
            navController.navigate(R.id.nav_notifications)
            intent.putExtra(EXTRA_OPEN_NOTIFICATIONS, false)
        }
    }

    override fun onStart() {
        super.onStart()
        val accounts = AppAccounts.getInstance()
        val selectedAccount = accounts.selectedAccount
        if (selectedAccount == null) {
            val intent = Intent(this, StartupActivity::class.java)
            intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_TASK_ON_HOME
            startActivity(intent)
            finish()
            return
        }
        activityViewModel.updateSelectedUser(selectedAccount)
    }

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        // Inflate the menu; this adds items to the action bar if it is present.
        //menuInflater.inflate(R.menu.main, menu)
        return true
    }

    override fun onSupportNavigateUp(): Boolean {
        val navController = findNavController(R.id.nav_host_fragment)
        return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
    }

    companion object {
        const val EXTRA_OPEN_NOTIFICATIONS: String = "EXTRA_OPEN_NOTIFICATIONS"
        const val EXTRA_NETWORK_ERROR = "EXTRA_NETWORK_ERROR"
        const val EXTRA_UNSPECIFIED_ERROR = "EXTRA_UNSPECIFIED_ERROR"
    }
}

class MainActivityViewModel : ViewModel() {
    val database = AppDatabase.getInstance()
    val user: MutableLiveData<User> = MutableLiveData<User>().apply {
        value = null
    }
    val notificationCnt: LiveData<Int> = database.notificationDao().getUnreadRowCount()
    val latestSemester: LiveData<List<Course>> = database.courseDao().getLatestSemester()

    @DelicateCoroutinesApi
    fun updateSelectedUser(account: Account) {
        GlobalScope.launch {
            user.postValue(database.userDao().findByUsername(account.name))
        }
    }
}
