package app.furmeet.events.brasilfurfest.schedule.adapters

import android.app.Activity
import android.content.Intent
import android.content.res.ColorStateList
import android.graphics.Paint
import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.DiffUtil
import com.adlerosn.brasilfurfest.R
import app.furmeet.events.brasilfurfest.helper.*
import app.furmeet.events.brasilfurfest.schedule.EventActivity
import app.furmeet.events.brasilfurfest.schedule.abstractDataTypes.dataholder.PeekableEvent
import app.furmeet.events.brasilfurfest.schedule.abstractDataTypes.managed.AttendeeConFavorite
import app.furmeet.events.brasilfurfest.schedule.managers.ScheduleManager
import app.furmeet.events.brasilfurfest.schedule.viewHolders.RecyclerViewHolder
import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.activity_search_filter_circle.view.*
import kotlinx.android.synthetic.main.activity_search_filter_item.view.*
import kotlin.math.roundToInt

class PeekableEventRecyclerViewAdapter(
        var items: MutableList<PeekableEvent>,
        val scheduleManager: ScheduleManager,
        val activity: Activity,
        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]
        holder.itemView.apply {
            eventTitle.text = it.title.solved
            startDay.text = it.timeRange.start.timeInMillis.formatAsDayOfWeek().capitalize()
            startText.text = it.timeRange.start.timeInMillis.formatAsHoursAndMinutes()
            finishText.text = it.timeRange.finish.timeInMillis.formatAsHoursAndMinutes()
            val ccls = circles!!
            ccls.removeAllViews()
            it.tags?.forEach {
                context.layoutInflater.inflate(R.layout.activity_search_filter_circle).apply {
                    tag_color.imageTintList = ColorStateList.valueOf(it.color)
                    ccls.addView(this)
                }
            }
            it.places?.forEach {
                context.layoutInflater.inflate(R.layout.activity_search_filter_circle).apply {
                    tag_color.imageTintList = ColorStateList.valueOf(it.color)
                    ccls.addView(this)
                }
            }
            context.layoutInflater.inflate(R.layout.activity_search_filter_circle).apply {
                tag_color.imageTintList = ColorStateList.valueOf(0x00000000)
                ccls.addView(this)
            }
            if (it.language == null) {
                flag.visibility = View.INVISIBLE
            } else {
                flag.visibility = View.VISIBLE
                flag.setImageDrawable(ContextCompat.getDrawable(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(context, R.drawable.ic_star_black_24dp))
            else
                starImage.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_star_border_black_24dp))
            val starValue = if (!showsStar) null else hasStar
            this.starButton.setOnClickListener { _ ->
                if (showsStar) {
                    if (hasStar) {
                        starImage.setImageDrawable(ContextCompat.getDrawable(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(context, R.color.colorBase20))
                        }
                        triggerViewRefresh()
                    } else {
                        starImage.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_star_black_24dp))
                        hasStar = true
                        event?.let {
                            scheduleManager.attendeeFavorites.add(
                                    AttendeeConFavorite(
                                            scheduleManager.convention,
                                            it
                                    )
                            ).apply {
                                triggerViewRefresh()
                            }
                        }
                    }
                }
            }
            this.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) {
                    Snackbar.make(holder.itemView.rootView, context.getString(R.string.you_removed_this_item), Snackbar.LENGTH_LONG).apply {
                        setActionTextColor(context.getColorCompat(R.color.colorBase20))
                        view.setBackgroundColor(context.getColorCompat(R.color.colorBase03))
                        view.let {
                            it.setPadding(
                                    it.paddingLeft,
                                    it.paddingTop,
                                    it.paddingRight,
                                    it.paddingBottom + 48.asDpToPx.roundToInt()
                            )
                            show()
                        }
                    }
                }
                bindPeekAndPop(
                        activity,
                        this as ViewGroup,
                        this,
                        starValue,
                        { this.starButton.callOnClick() },
                        { this.callOnClick() },
                        it
                )
            }
        }
    }
}