package net.pokeranalytics.android.ui.fragment.components.bottomsheet

import android.annotation.SuppressLint
import android.app.Activity.RESULT_OK
import android.app.Dialog
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import androidx.appcompat.view.ContextThemeWrapper
import androidx.fragment.app.FragmentManager
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import io.realm.RealmModel
import kotlinx.android.synthetic.main.fragment_bottom_sheet.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.ui.activity.EditableDataActivity
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor
import net.pokeranalytics.android.ui.view.rowrepresentable.SessionRow
import net.pokeranalytics.android.ui.view.rowrepresentable.TransactionRow
import java.util.*

open class BottomSheetFragment : BottomSheetDialogFragment() {

	lateinit var row: RowRepresentable
	lateinit var delegate: RowRepresentableDelegate
	var currentCurrency: Currency? = null
	var valueHasPlaceholder: Boolean = false

	private var isClearable: Boolean = true
	private var isDeletable: Boolean = false
	private var rowRepresentableEditDescriptors: ArrayList<RowRepresentableEditDescriptor>? = null

	companion object {

		const val REQUEST_CODE_ADD_NEW_OBJECT = 100

		fun create(
			fragmentManager: FragmentManager?,
			row: RowRepresentable,
			delegate: RowRepresentableDelegate,
			rowRepresentableEditDescriptors: ArrayList<RowRepresentableEditDescriptor>?,
			isClearable: Boolean? = true,
			currentCurrency: Currency? = null,
			isDeletable: Boolean? = false,
			valueHasPlaceholder: Boolean? = null
		): BottomSheetFragment {
			val bottomSheetFragment = row.bottomSheetType.newInstance()
			bottomSheetFragment.show(fragmentManager, "bottomSheet")
			bottomSheetFragment.row = row
			bottomSheetFragment.delegate = delegate
			bottomSheetFragment.rowRepresentableEditDescriptors = rowRepresentableEditDescriptors
			bottomSheetFragment.isClearable = isClearable ?: true
			bottomSheetFragment.isDeletable = isDeletable ?: true
			bottomSheetFragment.valueHasPlaceholder = valueHasPlaceholder ?: true
			bottomSheetFragment.currentCurrency = currentCurrency
			return bottomSheetFragment
		}
	}

	override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
		//TODO: When dependency 'com.google.android.material:material:1.1.0' will be available in stable version, upgrade and remove that
		val contextThemeWrapper = ContextThemeWrapper(activity, R.style.PokerAnalyticsTheme)
		return inflater.cloneInContext(contextThemeWrapper).inflate(R.layout.fragment_bottom_sheet, container, false)
	}

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


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

		// If we come from a creation of an object an everything is okay, we call
		// the delegate onRowValueChanged with the newly created object
		if (requestCode == REQUEST_CODE_ADD_NEW_OBJECT && resultCode == RESULT_OK && data != null) {
			val dataType = data.getIntExtra(EditableDataActivity.IntentKey.DATA_TYPE.keyName, 0)
			val primaryKey = data.getStringExtra(EditableDataActivity.IntentKey.PRIMARY_KEY.keyName)
			val pokerAnalyticsActivity = activity as PokerAnalyticsActivity
			val liveDataType = LiveData.values()[dataType]
			val proxyItem: RealmModel? = liveDataType.getData(pokerAnalyticsActivity.getRealm(), primaryKey)
			this.delegate.onRowValueChanged(proxyItem, this.row)
			dismiss()
		}
	}

	@SuppressLint("RestrictedApi")
	override fun setupDialog(dialog: Dialog?, style: Int) {
		super.setupDialog(dialog, style)
		dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
	}

	/**
	 * Init UI
	 */
	private fun initUI() {
		row.let {
			bottomSheetToolbar.title = row.localizedTitle(requireContext())
			bottomSheetToolbar.inflateMenu(R.menu.toolbar_bottom_sheet)
			bottomSheetToolbar.setOnMenuItemClickListener {
				false
			}
			bottomSheetToolbar.menu.findItem(R.id.actionCheck).isVisible = row.bottomSheetType.validationRequired
			bottomSheetToolbar.menu.findItem(R.id.actionClear).isVisible = row.bottomSheetType.clearRequired
			bottomSheetToolbar.menu.findItem(R.id.actionAdd).isVisible = row.bottomSheetType.addRequired

			// Menu
			bottomSheetToolbar.menu.findItem(R.id.actionClear).setOnMenuItemClickListener {
				delegate.onRowValueChanged(null, row)
				dismiss()
				true
			}

			bottomSheetToolbar.menu.findItem(R.id.actionDelete).setOnMenuItemClickListener {
				delegate.onRowDeleted(row)
				dismiss()
				true
			}

			bottomSheetToolbar.menu.findItem(R.id.actionAdd).setOnMenuItemClickListener {
				val liveData = when (row) {
					SessionRow.GAME -> LiveData.GAME
					SessionRow.BANKROLL, TransactionRow.BANKROLL -> LiveData.BANKROLL
					SessionRow.LOCATION -> LiveData.LOCATION
					SessionRow.TOURNAMENT_NAME -> LiveData.TOURNAMENT_NAME
					SessionRow.TOURNAMENT_FEATURE -> LiveData.TOURNAMENT_FEATURE
					TransactionRow.TYPE -> LiveData.TRANSACTION_TYPE
					else -> throw IllegalStateException("row $row does not have an associated LiveData value")
				}

				EditableDataActivity.newInstanceForResult(
					this,
					liveData,
					requestCode = REQUEST_CODE_ADD_NEW_OBJECT
				)

				true
			}
			bottomSheetToolbar.menu.findItem(R.id.actionCheck).setOnMenuItemClickListener {
				this.delegate.onRowValueChanged(getValue(), row)
				dismiss()
				true
			}

			bottomSheetToolbar.menu.findItem(R.id.actionClear).isVisible = isClearable
			bottomSheetToolbar.menu.findItem(R.id.actionDelete).isVisible = isDeletable
		}
	}

	/**
	 * Return the data list
	 */
	fun getData(): ArrayList<RowRepresentableEditDescriptor>? {
		return this.rowRepresentableEditDescriptors
	}

	open fun getValue(): Any? {
		return null
	}

}