package net.pokeranalytics.android.ui.fragment

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.isVisible
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import io.realm.Realm
import io.realm.RealmResults
import kotlinx.android.synthetic.main.fragment_data_list.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.model.interfaces.Deletable
import net.pokeranalytics.android.model.interfaces.Identifiable
import net.pokeranalytics.android.model.realm.Filter
import net.pokeranalytics.android.ui.activity.EditableDataActivity
import net.pokeranalytics.android.ui.activity.FiltersActivity
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.DeletableItemFragment
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.util.extensions.sorted


open class DataListFragment : DeletableItemFragment(), LiveRowRepresentableDataSource, RowRepresentableDelegate {

	companion object {
		const val REQUEST_CODE_DETAILS = 1000
	}

	private lateinit var identifiableClass: Class<out Deletable>

	private lateinit var dataType: LiveData
	private lateinit var items: RealmResults<out Deletable>

	/**
	 * Set fragment data
	 */
	open fun setData(dataType: Int) {

		this.dataType = LiveData.values()[dataType]
		this.identifiableClass = this.dataType.relatedEntity
		setToolbarTitle(this.dataType.pluralLocalizedTitle(requireContext()))

		this.items = this.retrieveItems(getRealm())
	}

	open fun retrieveItems(realm: Realm): RealmResults<out Deletable> {
        return realm.sorted(this.identifiableClass, editableOnly = true, filterableTypeUniqueIdentifier = dataType.subType)
	}

	override fun deletableItems() : List<Deletable> {
		return this.items
	}

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

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

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

		setDisplayHomeAsUpEnabled(true)

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

		val swipeToDelete = SwipeToDeleteCallback(dataListAdapter) { position ->
			val item = this.items[position]
			if (item != null) {
				val itemId = item.id
				deleteItem(dataListAdapter, items, itemId)
			} else {
				throw IllegalStateException("Item with position $position not found")
			}
		}

		val itemTouchHelper = ItemTouchHelper(swipeToDelete)

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

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

	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 onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) {

		when (this.dataType) {
			LiveData.FILTER -> {
				val intent = Intent()
				intent.putExtra(FiltersActivity.IntentKey.FILTER_ID.keyName, (row as Filter).id)
				activity?.setResult(Activity.RESULT_OK, intent)
				activity?.finish()
			}
			else -> {
				val identifier = (row as Identifiable).id
				EditableDataActivity.newInstanceForResult(this, this.dataType, identifier, REQUEST_CODE_DETAILS)
			}
		}
	}

	/**
	 * Update UI
	 */
	fun updateUI(showAddButton: Boolean) {
		this.addButton.isVisible = showAddButton
	}

}