package net.pokeranalytics.android.ui.fragment

import android.app.Activity
import android.app.Activity.RESULT_OK
import android.content.Intent
import android.os.Bundle
import android.view.*
import androidx.recyclerview.widget.LinearLayoutManager
import io.realm.kotlin.where
import kotlinx.android.synthetic.main.fragment_editable_data.*
import kotlinx.android.synthetic.main.fragment_filters.view.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.realm.Filter
import net.pokeranalytics.android.ui.activity.FilterDetailsActivity
import net.pokeranalytics.android.ui.activity.FiltersActivity
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.rowrepresentable.FilterCategoryRow
import timber.log.Timber


open class FiltersFragment : PokerAnalyticsFragment(), StaticRowRepresentableDataSource, RowRepresentableDelegate {

	companion object {
		const val REQUEST_CODE_FILTER_DETAILS = 100
	}

	private lateinit var parentActivity: PokerAnalyticsActivity
	private lateinit var rowRepresentableAdapter: RowRepresentableAdapter

	private var currentFilter: Filter? = null
	private var filterCopy: Filter? = null

	private var rows: ArrayList<RowRepresentable> = ArrayList()
	private var filterMenu: Menu? = null
	private var primaryKey: String? = null
	private var selectedRow: RowRepresentable? = null
	private var isUpdating = false

	override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
		return inflater.inflate(R.layout.fragment_filters, container, false)
	}

	override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
		super.onViewCreated(view, savedInstanceState)
		initUI()
		initData()
	}

	override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
		super.onActivityResult(requestCode, resultCode, data)

		if (requestCode == REQUEST_CODE_FILTER_DETAILS && resultCode == Activity.RESULT_OK) {

			/*
			Timber.d("onActivityResult: $requestCode")
			if (data != null && data.hasExtra(FilterDetailsActivity.IntentKey.FILTER_ID.keyName)) {
				val filterId = data.getStringExtra(FilterDetailsActivity.IntentKey.FILTER_ID.keyName)
				Timber.d("Updated filter: ${filterId}")
			}
			*/

			selectedRow?.let {
				rowRepresentableAdapter.refreshRow(it)
			}
		}
	}

	override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
		inflater?.inflate(R.menu.toolbar_editable_data, menu)
		this.filterMenu = menu
		updateMenuUI()
		super.onCreateOptionsMenu(menu, inflater)
	}

	override fun onBackPressed() {
		if (isUpdating) {
			cancelUpdates()
		} else {
			deleteFilter()
		}
	}

	override fun onOptionsItemSelected(item: MenuItem?): Boolean {
		when (item!!.itemId) {
			R.id.save -> validUpdates()
			R.id.delete -> deleteFilter()
		}
		return true
	}

	override fun adapterRows(): List<RowRepresentable>? {
		return rows
	}

	override fun stringForRow(row: RowRepresentable): String {
		// Return the number of selected filters for this category
		var selectedFilters = ""
		if (row is FilterCategoryRow) {
			currentFilter?.countBy(row)?.let { nbFilters ->
				if (nbFilters > 0) {
					selectedFilters = nbFilters.toString()
				}
			}
		}
		return selectedFilters
	}

	override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) {
		super.onRowSelected(position, row, fromAction)
		selectedRow = row
		currentFilter?.id?.let { filterId ->
			FilterDetailsActivity.newInstanceForResult(this, filterId, (row as FilterCategoryRow).ordinal, REQUEST_CODE_FILTER_DETAILS)
		}
	}

	/**
	 * Init UI
	 */
	private fun initUI() {
		parentActivity = activity as PokerAnalyticsActivity
		parentActivity.setSupportActionBar(toolbar)
		parentActivity.supportActionBar?.setDisplayHomeAsUpEnabled(true)
		setHasOptionsMenu(true)

		this.appBar.toolbar.title = getString(R.string.filter)

		val viewManager = LinearLayoutManager(requireContext())

		recyclerView.apply {
			setHasFixedSize(true)
			layoutManager = viewManager
		}
	}

	/**
	 * Init data
	 */
	private fun initData() {

		val realm = getRealm()

		//TODO: Remove that
		val filters = realm.where<Filter>().findAll()
		Timber.d("Filters: ${filters.size}")

		primaryKey?.let {
			currentFilter = Filter.getFilterBydId(realm, it)
			isUpdating = true
		} ?: run {
			realm.beginTransaction()
			currentFilter = Filter.newInstance(realm)
			realm.commitTransaction()
		}

		// Create a copy if the user cancels the updates
		currentFilter?.let {
			filterCopy = getRealm().copyFromRealm(it)
		}

		rows.clear()
		rows.addAll(FilterCategoryRow.values())

		this.rowRepresentableAdapter = RowRepresentableAdapter(this, this)
		this.recyclerView.adapter = rowRepresentableAdapter

	}

	/**
	 * Update menu UI
	 */
	private fun updateMenuUI() {
		filterMenu?.findItem(R.id.delete)?.isVisible = isUpdating
		filterMenu?.findItem(R.id.save)?.isVisible = true
	}

	/**
	 * Valid the  updates of the filter
	 */
	private fun validUpdates() {
		Timber.d("Valid filter updates")
		val filterId = currentFilter?.id ?: ""
		finishActivityWithResult(filterId)
	}

	/**
	 * Cancel the latest updates of the filter
	 */
	private fun cancelUpdates() {
		Timber.d("Cancel filter updates")

		val filterId = filterCopy?.id ?: ""

		val realm = getRealm()
		realm.beginTransaction()
		filterCopy?.let {
			realm.copyToRealmOrUpdate(it)
		}
		realm.commitTransaction()
		finishActivityWithResult(filterId)
	}

	/**
	 * Delete data
	 */
	private fun deleteFilter() {
		Timber.d("Delete filter")
		val realm = getRealm()
		realm.beginTransaction()
		currentFilter?.deleteFromRealm()
		realm.commitTransaction()

		finishActivityWithResult("")
	}

	/**
	 * Finish the activity with a result
	 */
	private fun finishActivityWithResult(uniqueIdentifier: String) {
		val intent = Intent()
		intent.putExtra(FiltersActivity.IntentKey.FILTER_ID.keyName, uniqueIdentifier)
		activity?.setResult(RESULT_OK, intent)
		activity?.finish()
	}

	/**
	 * Set fragment data
	 */
	fun setData(primaryKey: String?) {
		this.primaryKey = primaryKey
	}

}