package net.pokeranalytics.android.ui.adapter.components

import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import net.pokeranalytics.android.ui.view.BindableHolder
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowRepresentableDiffCallback
import net.pokeranalytics.android.ui.view.RowViewType

/**
 * An interface used to provide RowRepresentableAdapter content and value in the form of rows
 */
interface RowRepresentableDataSource {

	/**
	 * Returns a list of rows
	 */
	fun adapterRows(): ArrayList<RowRepresentable>

	/**
	 * Returns a boolean for a specific row
	 */
	fun boolForRow(row: RowRepresentable): Boolean {
		return false
	}

	/**
	 * Returns a string for a specific row
	 */
	fun stringForRow(row: RowRepresentable): String {
		return ""
	}

	/**
	 * Returns an action icon identifier for a specific row
	 */
	fun actionIconForRow(row: RowRepresentable): Int? {
		return 0
	}

	/**
	 * Manages:
	 * - label (string)
	 * - segmented control (live/online)
	 * - textfield (string)
	 * - switch (bool)
	 * - static content
	 * */

}

/**
 * A delegate used to propagate UI actions
 */
interface RowRepresentableDelegate {
	fun onRowSelected(row: RowRepresentable) {}
	fun onActionSelected(row: RowRepresentable) {}
}

/**
 * An adapter capable of displaying a list of RowRepresentables
 * @param rowRepresentableDataSource the datasource providing rows
 * @param rowRepresentableDelegate the delegate, notified of UI actions
 */
class RowRepresentableAdapter(
	var rowRepresentableDataSource: RowRepresentableDataSource,
	var rowRepresentableDelegate: RowRepresentableDelegate? = null
) :
	RecyclerView.Adapter<RecyclerView.ViewHolder>() {

	/**
	 * The list of rows to display
	 */
	private var rows: ArrayList<RowRepresentable> = ArrayList()

	init {
		this.rows = rowRepresentableDataSource.adapterRows()
	}

	override fun getItemViewType(position: Int): Int {
		return this.rows[position].viewType
	}

	override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
		val rowViewType: RowViewType = RowViewType.values()[viewType]
		return rowViewType.viewHolder(parent)
	}

	override fun getItemCount(): Int {
		return this.rows.size
	}

	override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
		val dynamicRow = this.rows[position]

		val listener = View.OnClickListener {
			rowRepresentableDelegate?.onRowSelected(dynamicRow)
		}

		val actionListener = View.OnClickListener {
			rowRepresentableDelegate?.onActionSelected(dynamicRow)
		}

		(holder as BindableHolder).bind(dynamicRow, this.rowRepresentableDataSource, listener, actionListener)
	}

	/**
	 * Refresh the row in the adapter
	 */
	fun refreshRow(row: RowRepresentable) {
		val index = rows.indexOf(row)
		if (index >= 0) {
			notifyItemChanged(index)
		}
	}

	/**
	 * Update UI
	 */
	fun updateRows(newRows: ArrayList<RowRepresentable>) {
		val diffResult = DiffUtil.calculateDiff(RowRepresentableDiffCallback(newRows, rows, rowRepresentableDataSource))
		this.rows = newRows
		diffResult.dispatchUpdatesTo(this)
	}

}