package net.pokeranalytics.android.ui.fragment

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.snackbar.Snackbar
import io.realm.Realm
import io.realm.RealmObject
import io.realm.RealmResults
import kotlinx.android.synthetic.main.fragment_data_list.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.interfaces.Manageable
import net.pokeranalytics.android.ui.activity.EditableDataActivity
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity
import net.pokeranalytics.android.ui.adapter.LiveRowRepresentableDataSource
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment
import net.pokeranalytics.android.ui.helpers.SwipeToDeleteCallback
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.ui.view.rowrepresentable.SettingRow
import net.pokeranalytics.android.util.extensions.showAlertDialog


class DataListFragment : PokerAnalyticsFragment(), LiveRowRepresentableDataSource, RowRepresentableDelegate {

	private lateinit var dataType: SettingRow
	private lateinit var items: RealmResults<*>
	private lateinit var dataListAdapter: RowRepresentableAdapter

	private var deletedItem: RealmObject? = null
	private var lastDeletedItemPosition: Int = 0

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

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

	override fun onResume() {
		super.onResume()
		this.recyclerView?.adapter?.notifyDataSetChanged()
	}

	override fun rowRepresentableForPosition(position: Int): RowRepresentable? {
		return this.items[position] as RowRepresentable
	}

	override fun numberOfRows(): Int {
		return this.items.size
	}

	override fun viewTypeForPosition(position: Int): Int {
		val viewType = (this.items[position] as RowRepresentable).viewType
		return if (viewType != -1) viewType else RowViewType.DATA.ordinal
	}

	override fun indexForRow(row: RowRepresentable): Int {
		return this.items.indexOf(row)
	}

	override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) {
		this.dataType.relatedResultsRepresentable?.let {
			EditableDataActivity.newInstance(
				requireContext(),
				it.ordinal,
				(row as Manageable).id
			)
		}
	}

	/**
	 * Init UI
	 */
	private fun initUI() {

		val activity = activity as PokerAnalyticsActivity

		// Avoid a bug during setting the title
		toolbar.title = ""

		activity.setSupportActionBar(toolbar)
		activity.supportActionBar?.setDisplayHomeAsUpEnabled(true)
		setHasOptionsMenu(true)

		val viewManager = LinearLayoutManager(requireContext())
		dataListAdapter = RowRepresentableAdapter(this, this)

		val swipeToDelete = SwipeToDeleteCallback(dataListAdapter) { position ->

			// Save the delete position & create a copy of the object
			val mRecentlyDeletedItem = rowRepresentableForPosition(position)
			lastDeletedItemPosition = position

			if (mRecentlyDeletedItem is RealmObject) {

				// Check if the object is valid for the deletion
				if ((mRecentlyDeletedItem as Manageable).isValidForDelete()) {
					deletedItem = getRealm().copyFromRealm(mRecentlyDeletedItem)
					getRealm().executeTransaction {
						mRecentlyDeletedItem.deleteFromRealm()
					}
					dataListAdapter.notifyItemRemoved(position)
					showUndoSnackBar()
				} else {
					dataListAdapter.notifyItemChanged(position)
					showAlertDialog(R.string.warning, (mRecentlyDeletedItem as Manageable).getFailedDeleteMessage())
				}
			}
		}

		val itemTouchHelper = ItemTouchHelper(swipeToDelete)

		recyclerView.apply {
			setHasFixedSize(true)
			layoutManager = viewManager
			adapter = dataListAdapter
			itemTouchHelper.attachToRecyclerView(this)
		}

		this.addButton.setOnClickListener {
			this.dataType.relatedResultsRepresentable?.let {
				EditableDataActivity.newInstance(
					requireContext(),
					dataType = it.ordinal,
					primaryKey = null
				)
			}
		}
	}

	/**
	 * Show undo snack bar
	 */
	private fun showUndoSnackBar() {
		val message = String.format(getString(R.string.data_deleted), this.dataType.localizedTitle(requireContext()))
		val snackBar = Snackbar.make(constraintLayout, message, Snackbar.LENGTH_LONG)
		snackBar.setAction(R.string.cancel) {
			getRealm().executeTransaction { realm ->
				deletedItem?.let {
					realm.copyToRealmOrUpdate(it)
					dataListAdapter.notifyItemInserted(lastDeletedItemPosition)
				}
			}
		}
		snackBar.show()
	}

	/**
	 * Set fragment data
	 */
	fun setData(dataType: Int) {
		this.dataType = SettingRow.values()[dataType]
		this.toolbar.title = this.dataType.localizedTitle(requireContext())
		val realm = Realm.getDefaultInstance()
		this.dataType.relatedResultsRepresentable?.let {
			this.items = it.items(realm)
		}
	}
}