package app.furmeet.events.system.schedule

import android.annotation.SuppressLint
import android.content.Intent
import android.content.res.ColorStateList
import android.graphics.Color
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.CalendarContract
import android.text.Spannable
import android.text.SpannableStringBuilder
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.widget.LinearLayout
import android.window.OnBackInvokedDispatcher
import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AlertDialog
import androidx.core.app.ActivityCompat
import androidx.core.graphics.toColor
import androidx.core.os.BuildCompat
import app.furmeet.events.system.CountdownActivity
import app.furmeet.events.bff.R
import app.furmeet.events.system.SplashActivity
import app.furmeet.events.system.TranslatableAppCompatActivityWithScheduleServiceWrapped
import app.furmeet.events.system.helper.*
import app.furmeet.events.system.helper.observables.Observable
import app.furmeet.events.system.helper.observables.Observer
import app.furmeet.events.system.schedule.abstractDataTypes.convention.FilterableNamedColoredAttribute
import app.furmeet.events.system.schedule.abstractDataTypes.managed.Actions
import app.furmeet.events.system.schedule.abstractDataTypes.managed.AttendeeConFavorite
import app.furmeet.events.system.schedule.managers.RemoteAssetsHolder
import app.furmeet.events.system.schedule.managers.ScheduleManagerGetter
import app.furmeet.events.bff.databinding.ActivityEventBinding
import app.furmeet.events.bff.databinding.ActivityEventContentKeypairBinding
import app.furmeet.events.bff.databinding.ActivityEventShareBinding
import com.google.gson.GsonBuilder


class EventActivity : TranslatableAppCompatActivityWithScheduleServiceWrapped() {

    private var fromNotification = false

    lateinit var binding: ActivityEventBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        ActivitiesForFragments[this.javaClass.simpleName] = this
        super.onCreate(savedInstanceState)
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
        window.statusBarColor = Color.TRANSPARENT
        binding = ActivityEventBinding.inflate(layoutInflater)
        val view = binding.root
        setContentView(view)
        resourcesAliased = this.resources
        setSupportActionBar(binding.toolbar)

        binding.toolbarLayout.setCollapsedTitleTextAppearance(R.style.CollapsedAppBar)
        binding.toolbarLayout.setExpandedTitleTextAppearance(R.style.ExpandedAppBar)
        scheduleManager.convention.colorScheme?.primaryRegular?.let { binding.toolbarLayout.setBackgroundColor(it) }

        val favorite = intent.getSerializableExtra("favorite") as AttendeeConFavorite
        val offerStar = intent.getBooleanExtra("offerStar", false)
        fromNotification = intent.getBooleanExtra("fromNotification", false)
        val event = favorite.findInConvention(scheduleManager.convention)
        binding.toolbarLayout.title = event?.titles?.solved ?: favorite.getString()
        binding.toolbarLayout.setExpandedTitleColor(ActivityCompat.getColor(this, R.color.colorWhiteDoNotInvert))
        binding.toolbarLayout.setCollapsedTitleTextColor(ActivityCompat.getColor(this, R.color.colorWhiteDoNotInvert))
        doAsync {
            uiThreadWithLogger {
                event?.assetImage?.solved?.fromCacheManagerToImageOf(binding.appBarImage)
                        ?: scheduleManager.convention.imageDefaultEvent?.solved?.fromCacheManagerToImageOf(binding.appBarImage)
            }
        }

        val timerClickListener = View.OnClickListener { _ ->
            Intent(this, CountdownActivity::class.java).let {
                it.putExtra("label", favorite.getString())
                it.putExtra("counter", favorite.timeRange.start.timeInMillis)
                it.putExtra("finishesAt", favorite.timeRange.finish.timeInMillis)
                startActivity(it)
            }
        }

        val keypairs = binding.root.findViewById<LinearLayout>(R.id.keypairs)
        keypairs.removeAllViews()
        inflateKeyPair(
                R.string.schedule_event_key_activity.getString(),
                favorite.getString(),
                keypairs
        )
        if (event?.subtitles?.solved?.isNotEmpty() == true)
            inflateKeyPair(
                    R.string.schedule_event_key_detail.getString(),
                    event.subtitles.solved!!,
                    keypairs
            )
        val whenButton = inflateKeyPair(
                R.string.schedule_event_key_when.getString(),
                R.string.schedule_event_key_when_formatted.getString().format(
                        favorite.timeRange.start.timeInMillis.formatAsLongDayOfWeekWithNumber(),
                        favorite.timeRange.start.timeInMillis.formatAsHoursAndMinutes(),
                        favorite.timeRange.finish.timeInMillis.formatAsHoursAndMinutes()
                ).capitalize(),
                keypairs
        ).apply {
            touchableIndicator.visibility = View.VISIBLE
            root.setOnClickListener(timerClickListener)
        }
        if (favorite.isSecondaryStringPlace) {
            inflateKeyPair(
                    R.string.schedule_event_key_place.getString(),
                    favorite.getSecondaryString(),
                    keypairs
            )
        }
        if (event != null) {
            if (event.places.isNotEmpty())
                inflateKeyPair(
                        event.places.size.pluralize(R.string.schedule_event_key_place, R.string.schedule_event_key_places).getString(),
                        formatSpannableWithColor(event.places),
                        keypairs
                )
            if (event.language != null)
                inflateKeyPair(
                        R.string.schedule_event_key_language.getString(),
                        event.language.language.getString(),
                        keypairs
                )
            event.descriptions.solved?.let {
                if (it.isNotEmpty() && it!="-")
                    inflateKeyPair(
                            R.string.schedule_event_key_description.getString(),
                            it,
                            keypairs
                    )
            }
            if (event.tags.isNotEmpty())
                inflateKeyPair(
                        event.tags.size.pluralize(R.string.schedule_event_key_category, R.string.schedule_event_key_categories).getString(),
                        formatSpannableWithColor(event.tags),
                        keypairs
                )
            if (event.conbookPages.isNotEmpty() && !(event.conbookPages.size == 1 && event.conbookPages[0] == 0))
                inflateKeyPair(
                        event.conbookPages.size.pluralize(R.string.schedule_event_key_on_conbooks_page, R.string.schedule_event_key_on_conbooks_pages).getString(),
                        event.conbookPages.map { it.toString() }.textuallyJoined,
                        keypairs
                )
            if (event.conbookId.isNotEmpty() && event.conbookId != "0")
                inflateKeyPair(
                        R.string.schedule_event_key_identified_on_conbook_as.getString(),
                        event.conbookId,
                        keypairs
                )
            if (event.attendableBy.isNotEmpty() && !(event.attendableBy.size == 1 && event.attendableBy[0].names.solved == "-%auto%-"))
                inflateKeyPair(
                        event.attendableBy.size.pluralize(R.string.schedule_event_key_elegible_registration, R.string.schedule_event_key_elegible_registrations).getString(),
                        event.attendableBy.map { it.names.solved!! }.textuallyJoined,
                        keypairs
                )
            @SuppressLint("RestrictedApi")
            if (event.hiddenFromTimeTable or scheduleManager.canAttend(event).not()) {
                binding.fab.visibility = View.GONE
                binding.fabCalendar.visibility = View.GONE
                binding.fabShare.visibility = View.GONE
            }
        }
        @SuppressLint("RestrictedApi")
        if (!offerStar) {
            binding.fab.visibility = View.GONE
            binding.fabCalendar.visibility = View.GONE
            binding.fabShare.visibility = View.GONE
        }

        scheduleManager.convention.colorScheme?.accentColor?.let {
            binding.fab.backgroundTintList = ColorStateList.valueOf(it)
            binding.fabCalendar.backgroundTintList = ColorStateList.valueOf(it)
        }

        binding.fab.setOnClickListener {
            R.drawable.ic_star_half_white_24dp.asImageOf(binding.fab)
            if (favorite in scheduleManager.attendeeFavorites)
                scheduleManager.attendeeFavorites.remove(favorite)
            else {
                scheduleManager.attendeeFavorites.add(favorite)
                begForNotificationPermission()
            }
        }
        binding.fab.isLongClickable = true
        binding.fab.setOnLongClickListener {
            longToast(R.string.add_or_remove_favorite.getString())
            true
        }
        binding.fabCalendar.setOnClickListener { _ ->
            val intent = Intent(Intent.ACTION_EDIT)
            intent.type = "vnd.android.cursor.item/event"
            intent.putExtra(CalendarContract.Events.TITLE, favorite.getString())
            if (event != null) {
                intent.putExtra(CalendarContract.Events.EVENT_LOCATION, event.places.map {
                    it.names.solved ?: ""
                }.textuallyJoined)
                intent.putExtra(CalendarContract.Events.DESCRIPTION, event.descriptions.solved
                        ?: "")
            } else if (favorite.kind == Actions.Intention.ROOMPARTY) {
                intent.putExtra(CalendarContract.Events.EVENT_LOCATION, favorite.getSecondaryString())
            }
            intent.putExtra(
                    CalendarContract.EXTRA_EVENT_BEGIN_TIME,
                    favorite.timeRange.start.timeInMillis
            )
            intent.putExtra(
                    CalendarContract.EXTRA_EVENT_END_TIME,
                    favorite.timeRange.finish.timeInMillis
            )
            startActivity(intent)
        }
        binding.fabShare.isLongClickable = true
        binding.fabShare.setOnClickListener {
            val gson = GsonBuilder().create()
            val link = RemoteAssetsHolder.remoteAssets.prefixRoomParty + Uri.encode(gson.toJson(favorite))
            val dialog = AlertDialog.Builder(this).create()
            dialog.setTitle(R.string.event_share_question.getString())
            val innerBinding = ActivityEventShareBinding.inflate(layoutInflater)
            innerBinding.btnLink.setOnClickListener {
                toClipboard(link, "Room party link", true)
                startActivity(Intent.createChooser(Intent(Intent.ACTION_SEND).apply { type = "text/plain"; putExtra(Intent.EXTRA_TEXT, link) }, null))
                dialog.dismiss()
            }
            innerBinding.btnQr.setOnClickListener {
                startActivity(Intent(this, QRCodeViewerActivity::class.java).apply { putExtra("data", link) })
                dialog.dismiss()
            }
            dialog.setView(innerBinding.root)
            dialog.show()
        }
        binding.fabShare.setOnLongClickListener {
            longToast(R.string.shows_you_how_you_can_share_this.getString())
            true
        }
        if (favorite.isShareable.not())
            @SuppressLint("RestrictedApi")
            binding.fabShare.visibility = View.INVISIBLE
        binding.fabCalendar.isLongClickable = true
        binding.fabCalendar.setOnLongClickListener {
            it.context.longToast(R.string.adds_to_your_agenda_app.getString())
            true
        }
        whenButton.root.isLongClickable = true
        whenButton.root.setOnLongClickListener {
            longToast(R.string.opens_timer.getString())
            true
        }
        scheduleManager.addObserver(Observer { _: Observable<Any?>, _: Any? ->
            if (favorite in scheduleManager.attendeeFavorites)
                R.drawable.ic_star_white_24dp.asImageOf(binding.fab)
            else
                R.drawable.ic_star_border_white_24dp.asImageOf(binding.fab)
        }.apply { this.update(Observable(), null) })
        onBackPressDispatcherAddCallbackCompat { handleBackPressed() }
    }

    private fun inflateKeyPair(key: String, value: CharSequence, into: ViewGroup? = null) =
            ActivityEventContentKeypairBinding.inflate(layoutInflater).apply {
                textKey.text = key
                textValue.text = value
                into?.addView(this.root)
                touchableIndicator.visibility = View.GONE
            }

    private fun handleBackPressed() {
        if (!fromNotification)
            finish()
        else {
            val intent = Intent(this, SplashActivity::class.java)
            intent.flags =
                Intent.FLAG_ACTIVITY_NEW_TASK or
                        Intent.FLAG_ACTIVITY_TASK_ON_HOME
            intent.putExtra("fastStart", true)
            this.startActivity(intent)
            this.finish()
        }
    }

    private fun formatSpannableWithColor(collection: List<FilterableNamedColoredAttribute>): Spannable =
            collection.map {
                SpannableString(
                        it.names.solved!!,
                        RoundedBackgroundAndForegroundColorsSpan(
                                it.color,
                                it.color.decideBestForegroundColor(
                                        applicationContext.getColorCompat(R.color.colorBase03),
                                        applicationContext.getColorCompat(R.color.colorBase21)
                                )
                        )
                )
            }.textuallyJoined.let { SpannableStringBuilder().append(it).append(" ") }
}
