package net.pokeranalytics.android.ui.fragment.data

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import androidx.appcompat.app.AlertDialog
import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.ConfigurationException
import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.model.interfaces.Deletable
import net.pokeranalytics.android.model.interfaces.Savable
import net.pokeranalytics.android.model.interfaces.SaveValidityStatus
import net.pokeranalytics.android.ui.activity.DataListActivity
import net.pokeranalytics.android.ui.activity.EditableDataActivity
import net.pokeranalytics.android.ui.fragment.components.RealmFragment

open class DataManagerFragment : RealmFragment() {

	lateinit var item: Deletable

	lateinit var liveDataType: LiveData
	protected var primaryKey: String? = null

	var deleteButtonShouldAppear = false
		set(value) {
			field = value
			this.updateMenuUI()
		}

	var saveButtonShouldAppear = true
		set(value) {
			field = value
			this.updateMenuUI()
		}

	protected var dataType: Int? = null

	private var editableMenu: Menu? = null

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

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

	/**
	 * Update menu UI
	 */
	private fun updateMenuUI() {
		editableMenu?.findItem(R.id.delete)?.isVisible = this.deleteButtonShouldAppear
		editableMenu?.findItem(R.id.save)?.isVisible = this.saveButtonShouldAppear
	}

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

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

		this.item = this.liveDataType.updateOrCreate(this.getRealm(), primaryKey)
		this.deleteButtonShouldAppear = this.primaryKey != null

	}

	/**
	 * Save data
	 */
	protected open fun saveData() {

		val savable = this.item
		this.willSaveData()

		when (savable) {
			is Savable -> {
				val status = savable.getSaveValidityStatus(realm = this.getRealm())
				when (status) {
					SaveValidityStatus.VALID -> {
						this.getRealm().executeTransaction {
							val managedItem = it.copyToRealmOrUpdate(this.item)
							if (managedItem is Savable) {
								val uniqueIdentifier = managedItem.id
								finishActivityWithResult(uniqueIdentifier)
							}
						}
						onDataSaved()
					}
					else -> {
						val message = savable.getFailedSaveMessage(status)
						val builder = AlertDialog.Builder(requireContext())
							.setMessage(message)
							.setNegativeButton(R.string.ok, null)
						builder.show()
					}
				}

			}
			else -> {
				throw ConfigurationException("Save action called on un-Savable object")
			}
		}

	}

	open fun willSaveData() {

	}

	/**
	 * Delete data
	 */
	protected open fun deleteData() {

		val realm = this.getRealm()

		if (this.item.isValidForDelete(realm)) {
			val intent = Intent()
			intent.putExtra(DataListActivity.IntentKey.ITEM_DELETED.keyName, this.item.id)
			activity?.setResult(Activity.RESULT_OK, intent)
			activity?.finish()
		} else {
			val status = this.item.getDeleteStatus(requireContext(), realm)
			val message = this.item.getFailedDeleteMessage(status)
			val builder = AlertDialog.Builder(requireContext())
				.setMessage(message)
				.setNegativeButton(R.string.ok, null)
			builder.show()
		}
	}

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

	open fun onDataSaved() {}


}