package app.furmeet.events.system.schedule.adapters

import android.app.Activity
import android.content.Intent
import android.content.res.ColorStateList
import android.graphics.Color
import android.graphics.Paint
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.DiffUtil
import app.furmeet.events.bff.R
import app.furmeet.events.system.helper.*
import app.furmeet.events.system.schedule.EventActivity
import app.furmeet.events.system.schedule.abstractDataTypes.dataholder.PeekableEvent
import app.furmeet.events.system.schedule.abstractDataTypes.managed.AttendeeConFavorite
import app.furmeet.events.system.schedule.managers.ScheduleManager
import app.furmeet.events.system.schedule.viewHolders.RecyclerViewHolder
import app.furmeet.events.bff.databinding.ActivitySearchFilterItemBinding
import java.util.*

class PeekableEventRecyclerViewAdapter(
        var items: MutableList<PeekableEvent>,
        val scheduleManager: ScheduleManager,
        val activity: Activity,
        val accentColor: Int?,
        val triggerViewRefresh: () -> Unit
) : RecyclerViewAdapter() {
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerViewHolder {
        return RecyclerViewHolder(parent.context.layoutInflater.inflate(R.layout.activity_search_filter_item))
    }

    fun onDataChanged(newData: List<PeekableEvent>) {
        val oldData = items
        activity.runOnUiThread {
            items = newData.toMutableList()
            val diff = DiffUtil.calculateDiff(ListDiffCallback(oldData, newData))
            diff.dispatchUpdatesTo(this)
        }
    }

    override fun getItemCount(): Int = items.size

    override fun onBindViewHolder(holder: RecyclerViewHolder, position: Int) {
        val it = items[position]
        ActivitySearchFilterItemBinding.bind(holder.itemView).apply {
            eventTitle.text = it.title.solved
            startDay.text = it.timeRange.start.timeInMillis.formatAsDayOfWeek()
                .replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
            startText.text = it.timeRange.start.timeInMillis.formatAsHoursAndMinutes()
            finishText.text = it.timeRange.finish.timeInMillis.formatAsHoursAndMinutes()
            circles.removeAllViews()
            it.tags?.forEach {
                root.context.layoutInflater.inflate(R.layout.activity_search_filter_circle).apply {
                    this.findViewById<ImageView>(R.id.tag_color)!!.imageTintList = ColorStateList.valueOf(it.color)
                    circles.addView(this)
                }
            }
            it.places?.forEach {
                root.context.layoutInflater.inflate(R.layout.activity_search_filter_circle).apply {
                    this.findViewById<ImageView>(R.id.tag_color)!!.imageTintList = ColorStateList.valueOf(it.color)
                    circles.addView(this)
                }
            }
            root.context.layoutInflater.inflate(R.layout.activity_search_filter_circle).apply {
                this.findViewById<ImageView>(R.id.tag_color)!!.imageTintList = ColorStateList.valueOf(0x00000000)
                circles.addView(this)
            }
            if (it.language == null) {
                flag.visibility = View.INVISIBLE
            } else {
                flag.visibility = View.VISIBLE
                flag.setImageDrawable(ContextCompat.getDrawable(root.context, it.language.drawableId))
            }
            val favorites = scheduleManager.attendeeFavorites.toList()
            val event = scheduleManager.convention.events.firstOrNull { ev -> ev.uuid == it.id }
            val showsStar = event?.let {
                scheduleManager.canAttend(it)
                        && !it.hiddenFromTimeTable
            } ?: true
            var hasStar = favorites.any { fav -> it.similarEnough(fav) }
            if (showsStar)
                starImage.visibility = View.VISIBLE
            else
                starImage.visibility = View.INVISIBLE
            if (hasStar)
                starImage.setImageDrawable(ContextCompat.getDrawable(root.context, R.drawable.ic_star_black_24dp))
            else
                starImage.setImageDrawable(ContextCompat.getDrawable(root.context, R.drawable.ic_star_border_black_24dp))
            accentColor?.let {
                starImage.imageTintList = ColorStateList.valueOf(it)
            }
            val starValue = if (!showsStar) null else hasStar
            this.starButton.setOnClickListener { _ ->
                if (showsStar) {
                    if (hasStar) {
                        starImage.setImageDrawable(ContextCompat.getDrawable(root.context, R.drawable.ic_star_border_black_24dp))
                        hasStar = false
                        scheduleManager.attendeeFavorites.toList().firstOrNull { fav ->
                            it.similarEnough(fav)
                        }?.let {
                            scheduleManager.attendeeFavorites.remove(it)
                        }
                        val newEvent = scheduleManager.convention.events.firstOrNull { ev -> ev.conbookId == it.id }
                        if (newEvent == null) {
                            starButton.visibility = View.INVISIBLE
                            eventTitle.paintFlags = eventTitle.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
                            eventTitle.setTextColor(ContextCompat.getColor(root.context, R.color.colorBase20))
                        }
                        triggerViewRefresh()
                    } else {
                        starImage.setImageDrawable(ContextCompat.getDrawable(root.context, R.drawable.ic_star_black_24dp))
                        hasStar = true
                        event?.let {
                            scheduleManager.attendeeFavorites.add(
                                    AttendeeConFavorite(
                                            scheduleManager.convention,
                                            it
                                    )
                            ).apply {
                                triggerViewRefresh()
                            }
                            activity.begForNotificationPermission()
                        }
                    }
                }
            }
            root.setOnClickListener { _ ->
                val favorite: AttendeeConFavorite? = scheduleManager.attendeeFavorites.toList().firstOrNull { fav ->
                    it.similarEnough(fav)
                } ?: event?.let {
                    AttendeeConFavorite(
                            scheduleManager.convention,
                            it
                    )
                }
                favorite?.let { fav ->
                    activity.startActivity(
                            Intent(activity, EventActivity::class.java).apply {
                                putExtra("favorite", fav)
                                putExtra("offerStar", showsStar)
                            }
                    )
                }
                if (favorite == null) {
                    root.context.longToast(root.context.getString(R.string.you_removed_this_item))
                }
                bindPeekAndPop(
                        activity,
                        this.root as ViewGroup,
                        this.root,
                        starValue,
                        { this.starButton.callOnClick() },
                        { this.root.callOnClick() },
                        it
                )
            }
        }
    }
}