/*
 * Copyright 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.emoji2.emojipicker

import android.content.Context
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View.GONE
import android.view.View.OnClickListener
import android.view.View.OnLongClickListener
import android.view.View.VISIBLE
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams
import android.view.accessibility.AccessibilityEvent
import android.widget.GridLayout
import android.widget.ImageView
import android.widget.PopupWindow
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import kotlin.math.roundToInt

/** A [ViewHolder] containing an emoji view and emoji data.  */
internal class EmojiViewHolder(
    context: Context,
    parent: ViewGroup,
    layoutInflater: LayoutInflater,
    width: Int,
    height: Int,
    private val stickyVariantProvider: StickyVariantProvider,
    private val onEmojiPickedListener: EmojiViewHolder.(EmojiViewItem) -> Unit,
    private val onEmojiPickedFromPopupListener: EmojiViewHolder.(String) -> Unit
) : ViewHolder(
    layoutInflater
        .inflate(R.layout.emoji_view_holder, parent, /* attachToRoot = */false)
) {
    private val onEmojiClickListener: OnClickListener = OnClickListener { v ->
        v.findViewById<EmojiView>(R.id.emoji_view).emoji?.let {
            onEmojiPickedListener(EmojiViewItem(it.toString(), emojiViewItem.variants))
        }
    }

    private val onEmojiLongClickListener: OnLongClickListener = OnLongClickListener {
        showPopupWindow(layoutInflater, emojiView) {
            PopupViewHelper(context).fillPopupView(
                it,
                layoutInflater,
                emojiView.measuredWidth,
                emojiView.measuredHeight,
                emojiViewItem.variants,
                clickListener = { view ->
                    val emojiPickedInPopup = (view as EmojiView).emoji.toString()
                    onEmojiPickedFromPopupListener(emojiPickedInPopup)
                    onEmojiClickListener.onClick(view)
                    // variants[0] is always the base (i.e., primary) emoji
                    stickyVariantProvider.update(emojiViewItem.variants[0], emojiPickedInPopup)
                    this.dismiss()
                    // Hover on the base emoji after popup dismissed
                    emojiView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER)
                }
            )
        }
        true
    }

    private val emojiView: EmojiView
    private val indicator: ImageView
    private lateinit var emojiViewItem: EmojiViewItem

    init {
        itemView.layoutParams = LayoutParams(width, height)
        emojiView = itemView.findViewById(R.id.emoji_view)
        emojiView.isClickable = true
        emojiView.setOnClickListener(onEmojiClickListener)
        indicator = itemView.findViewById(R.id.variant_availability_indicator)
    }

    fun bindEmoji(
        emojiViewItem: EmojiViewItem,
    ) {
        emojiView.emoji = emojiViewItem.emoji
        this.emojiViewItem = emojiViewItem

        if (emojiViewItem.variants.isNotEmpty()) {
            indicator.visibility = VISIBLE
            emojiView.setOnLongClickListener(onEmojiLongClickListener)
            emojiView.isLongClickable = true
        } else {
            indicator.visibility = GONE
            emojiView.setOnLongClickListener(null)
            emojiView.isLongClickable = false
        }
    }

    private fun showPopupWindow(
        layoutInflater: LayoutInflater,
        parent: EmojiView,
        init: PopupWindow.(GridLayout) -> Unit
    ) {
        val popupView = layoutInflater
            .inflate(R.layout.variant_popup, null, false)
            .findViewById<GridLayout>(R.id.variant_popup)
        PopupWindow(popupView, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, false).apply {
            init(popupView)
            val location = IntArray(2)
            parent.getLocationInWindow(location)
            // Make the popup view center align with the target emoji view.
            val x =
                location[0] + parent.width / 2f - popupView.columnCount * parent.width / 2f
            val y = location[1] - popupView.rowCount * parent.height
            isOutsideTouchable = true
            isTouchable = true
            animationStyle = R.style.VariantPopupAnimation
            showAtLocation(
                parent,
                Gravity.NO_GRAVITY,
                x.roundToInt(),
                y
            )
        }
    }
}