/**
 * ProjectLaogai
 *
 * Copyright 2019-2020  <seil0@mosad.xyz>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 *
 */

package org.mosad.seil0.projectlaogai

import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.nfc.NfcAdapter
import android.nfc.NfcManager
import android.nfc.tech.NfcA
import android.os.Bundle
import android.util.Log
import android.util.TypedValue
import android.view.Menu
import android.view.MenuItem
import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.GravityCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentTransaction
import androidx.fragment.app.commit
import com.afollestad.aesthetic.Aesthetic
import com.afollestad.aesthetic.NavigationViewMode
import com.google.android.material.navigation.NavigationView
import org.mosad.seil0.projectlaogai.controller.NFCMensaCard
import org.mosad.seil0.projectlaogai.controller.cache.CacheController
import org.mosad.seil0.projectlaogai.controller.preferences.EncryptedPreferences
import org.mosad.seil0.projectlaogai.controller.preferences.Preferences
import org.mosad.seil0.projectlaogai.databinding.ActivityMainBinding
import org.mosad.seil0.projectlaogai.fragments.*
import org.mosad.seil0.projectlaogai.util.NotificationUtils
import kotlin.system.measureTimeMillis

/**
 * TODO save the current fragment to show it when the app is restarted
 */
class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {

    private lateinit var binding: ActivityMainBinding
    private var activeFragment: Fragment = HomeFragment() // the currently active fragment, home at the start

    private lateinit var adapter: NfcAdapter
    private lateinit var pendingIntent: PendingIntent
    private lateinit var intentFiltersArray: Array<IntentFilter>
    private lateinit var techListsArray: Array<Array<String>>
    private var useNFC = false

    override fun onCreate(savedInstanceState: Bundle?) {
        Aesthetic.attach(this)
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        setSupportActionBar(binding.appBar.toolbar)

        // load mensa, timetable and color
        load()
        initAesthetic()
        initForegroundDispatch()

        val toggle = ActionBarDrawerToggle(
            this, binding.drawerLayout, binding.appBar.toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close
        )
        binding.drawerLayout.addDrawerListener(toggle)
        toggle.syncState()

        binding.navView.setNavigationItemSelectedListener(this)

        // based on the intent we get, call readBalance or open a Fragment
        when (intent.action) {
            NfcAdapter.ACTION_TECH_DISCOVERED -> NFCMensaCard.readBalance(intent, this)
            getString(R.string.intent_action_mensaFragment) -> activeFragment = MensaFragment()
            getString(R.string.intent_action_timetableFragment) -> activeFragment = TimetableFragment()
            getString(R.string.intent_action_moodleFragment) -> activeFragment = MoodleFragment()
            getString(R.string.intent_action_gradesFragment) -> activeFragment = GradesFragment()
            else -> activeFragment = HomeFragment()
        }

        supportFragmentManager.commit {
            replace(R.id.fragment_container, activeFragment, activeFragment.javaClass.simpleName)
        }
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)

        if (NfcAdapter.ACTION_TECH_DISCOVERED == intent.action)
            NFCMensaCard.readBalance(intent, this)
    }


    override fun onResume() {
        super.onResume()
        Aesthetic.resume(this)
        if(useNFC)
            adapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray)

    }

    override fun onPause() {
        super.onPause()
        Aesthetic.pause(this)
        if(useNFC)
            adapter.disableForegroundDispatch(this)
    }

    override fun onBackPressed() {
        if (binding.drawerLayout.isDrawerOpen(GravityCompat.START)) {
            binding.drawerLayout.closeDrawer(GravityCompat.START)
        } else {
            // TODO only call on double tap
            super.onBackPressed()
        }
    }

    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 onOptionsItemSelected(item: MenuItem): Boolean {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        return when (item.itemId) {
            R.id.action_settings -> true
            else -> super.onOptionsItemSelected(item)
        }
    }

    override fun onNavigationItemSelected(item: MenuItem): Boolean {
        // Handle navigation view item clicks here.
        activeFragment = when(item.itemId) {
            R.id.nav_home -> HomeFragment()
            R.id.nav_mensa -> MensaFragment()
            R.id.nav_timetable -> TimetableFragment()
            R.id.nav_moodle -> MoodleFragment()
            R.id.nav_grades -> GradesFragment()
            R.id.nav_settings -> SettingsFragment()
            else -> HomeFragment()
        }

        val fragmentTransaction: FragmentTransaction = supportFragmentManager.beginTransaction()
        fragmentTransaction.replace(R.id.fragment_container, activeFragment)
        fragmentTransaction.commit()

        binding.drawerLayout.closeDrawer(GravityCompat.START)

        return true
    }

    /**
     * load the mensa menus of the current week
     */
    private fun load() {
        val startupTime = measureTimeMillis {
            Preferences.load(this) // load the settings, must be finished before doing anything else
            CacheController(this) // load the cache
            EncryptedPreferences.load(this)
            NotificationUtils(this)
        }
        Log.i(javaClass.simpleName, "Startup completed in $startupTime ms")
    }

    private fun initAesthetic() {
        // If we haven't set any defaults, do that now
        if (Aesthetic.isFirstTime) {
            // set the default theme at the first app start
            Aesthetic.config {
                activityTheme(R.style.AppTheme_Light)
                apply()
            }

            // show the onboarding activity
            startActivity(Intent(this, OnboardingActivity::class.java))
            finish()
        }

        Aesthetic.config {
            colorPrimary(Preferences.colorPrimary)
            colorPrimaryDark(Preferences.colorPrimary)
            colorAccent(Preferences.colorAccent)
            navigationViewMode(NavigationViewMode.SELECTED_ACCENT)
            apply()
        }

        // set theme color values
        val out = TypedValue()
        this.theme.resolveAttribute(R.attr.themePrimary, out, true)
        Preferences.themePrimary = out.data

        this.theme.resolveAttribute(R.attr.themeSecondary, out, true)
        Preferences.themeSecondary = out.data
    }

    private fun initForegroundDispatch() {
        val nfcManager = this.getSystemService(Context.NFC_SERVICE) as NfcManager
        val nfcAdapter = nfcManager.defaultAdapter

        if (nfcAdapter != null) {
            useNFC = true
            intentFiltersArray = arrayOf(IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED).apply { addDataType("*/*") })
            techListsArray = arrayOf(arrayOf(NfcA::class.java.name))
            adapter = NfcAdapter.getDefaultAdapter(this)
            pendingIntent = PendingIntent.getActivity(
                this, 0,
                Intent(this, javaClass).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0
            )
        }
    }

}
