package net.pokeranalytics.android.ui.adapter

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.AppCompatTextView
import androidx.recyclerview.widget.RecyclerView
import io.realm.RealmResults
import kotlinx.android.synthetic.main.row_transaction.view.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.realm.Transaction
import net.pokeranalytics.android.ui.view.BindableHolder
import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.util.NULL_TEXT
import net.pokeranalytics.android.util.extensions.getMonthAndYear
import java.util.*
import kotlin.collections.HashMap


/**
 * An adapter capable of displaying a list of RowRepresentables
 * @param dataSource the datasource providing rows
 * @param delegate the delegate, notified of UI actions
 */
class FeedTransactionRowRepresentableAdapter(
	var delegate: RowRepresentableDelegate? = null,
	var realmTransactions: RealmResults<Transaction>,
	var distinctTransactionsHeaders: RealmResults<Transaction>
) :
	RecyclerView.Adapter<RecyclerView.ViewHolder>() {

	private var headersPositions = HashMap<Int, Date?>()
	private lateinit var sortedHeaders: SortedMap<Int, Date?>

	init {
		refreshData()
	}

	/**
	 * Display a transaction view
	 */
	inner class RowTransactionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder {
		fun bind(position: Int, row: Transaction?, adapter: FeedTransactionRowRepresentableAdapter) {

			itemView.transactionRow.setData(row as Transaction)
			val listener = View.OnClickListener {
				adapter.delegate?.onRowSelected(position, row)
			}
			itemView.transactionRow.setOnClickListener(listener)
		}
	}

	/**
	 * Display a header
	 */
	inner class HeaderTitleViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder {
		fun bind(title: String) {
			// Title
			itemView.findViewById<AppCompatTextView>(R.id.title)?.let {
				it.text = title
			}
		}
	}

	override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
		return if (viewType == RowViewType.ROW_TRANSACTION.ordinal) {
			val layout = LayoutInflater.from(parent.context).inflate(R.layout.row_transaction, parent, false)
			RowTransactionViewHolder(layout)
		} else {
			val layout = LayoutInflater.from(parent.context).inflate(R.layout.row_header_title, parent, false)
			HeaderTitleViewHolder(layout)
		}

	}


	override fun getItemViewType(position: Int): Int {
		if (sortedHeaders.containsKey(position)) {
			return RowViewType.HEADER_TITLE.ordinal
		} else {
			return RowViewType.ROW_TRANSACTION.ordinal
		}
	}

	override fun getItemCount(): Int {
		return realmTransactions.size + distinctTransactionsHeaders.size
	}

	override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
		if (holder is RowTransactionViewHolder) {
			holder.bind(position, getTransactionForPosition(position), this)
		} else if (holder is HeaderTitleViewHolder) {
			holder.bind(getHeaderForPosition(position))
		}
	}

	/**
	 * Return the header
	 */
	private fun getHeaderForPosition(position: Int): String {
		if (sortedHeaders.containsKey(position)) {
			val realmHeaderPosition = sortedHeaders.keys.indexOf(position)
			return distinctTransactionsHeaders[realmHeaderPosition]?.date?.getMonthAndYear() ?: ""
		}
		return NULL_TEXT
	}

	/**
	 * Get real index
	 */
	private fun getTransactionForPosition(position: Int): Transaction? {

		// Row position
		var headersBefore = 0
		for (key in sortedHeaders.keys) {
			if (position > key) {
				headersBefore++
			} else {
				break
			}
		}

		return realmTransactions[position - headersBefore]
	}

	/**
	 * Refresh headers positions
	 */
	fun refreshData() {

		headersPositions.clear()

		val start = System.currentTimeMillis()

		var previousYear = Int.MAX_VALUE
		var previousMonth = Int.MAX_VALUE

		val calendar = Calendar.getInstance()

		// Add headers if the date doesn't exist yet
		for ((index, transaction) in realmTransactions.withIndex()) {
			calendar.time = transaction.date
			if (checkHeaderCondition(calendar, previousYear, previousMonth)) {
				headersPositions[index + headersPositions.size] = transaction.date
				previousYear = calendar.get(Calendar.YEAR)
				previousMonth = calendar.get(Calendar.MONTH)
			}
		}

		sortedHeaders = headersPositions.toSortedMap()
	}

	/**
	 * Check if we need to add a header
	 * Can be change to manage different condition
	 */
	private fun checkHeaderCondition(currentCalendar: Calendar, previousYear: Int, previousMonth: Int): Boolean {
		return currentCalendar.get(Calendar.YEAR) == previousYear && currentCalendar.get(Calendar.MONTH) < previousMonth || (currentCalendar.get(Calendar.YEAR) < previousYear)

	}


}