package net.pokeranalytics.android.ui.activity.components

import android.Manifest.permission.ACCESS_FINE_LOCATION
import android.content.pm.ActivityInfo
import android.content.pm.PackageManager
import android.os.Bundle
import android.os.PersistableBundle
import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.crashlytics.android.Crashlytics
import com.google.android.libraries.places.api.model.PlaceLikelihood
import io.realm.Realm
import net.pokeranalytics.android.model.realm.Location
import net.pokeranalytics.android.util.LocationManager
import java.util.*


open class PokerAnalyticsActivity : AppCompatActivity() {

	companion object {
		const val PERMISSION_REQUEST_ACCESS_FINE_LOCATION = 1000
		const val PERMISSION_REQUEST_READ_EXTERNAL_STORAGE = 1001
		const val PLAY_SERVICES_RESOLUTION_REQUEST = 2000
	}

	private var realm: Realm? = null
	private var permissionCallback: ((granted: Boolean) -> Unit)? = null


	// Lifecycle

	override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
		super.onCreate(savedInstanceState, persistentState)
		Crashlytics.log("$this.localClassName onCreate")
		requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT // fixes crash
	}

	override fun onResume() {
		super.onResume()
		Crashlytics.log("$this.localClassName onResume")
	}

	override fun onPause() {
		super.onPause()
		Crashlytics.log("$this.localClassName onPause")
	}

	override fun onDestroy() {
		super.onDestroy()
		Crashlytics.log("$this.localClassName onDestroy")
		this.realm?.close()
	}

	override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
		super.onRequestPermissionsResult(requestCode, permissions, grantResults)

		when (requestCode) {
			PERMISSION_REQUEST_ACCESS_FINE_LOCATION -> {
				if (permissions.isNotEmpty() && permissions[0] == ACCESS_FINE_LOCATION
					&& grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED
				) {
					permissionCallback?.invoke(true)
				} else {
					permissionCallback?.invoke(false)
					// permission denied, boo! Disable the
					// functionality that depends on this permission.
					// showMessage(getString(R.string.error));
				}
			}
		}

	}

	override fun onOptionsItemSelected(item: MenuItem?): Boolean {
		item?.let {
			if (it.itemId == android.R.id.home) {
				onBackPressed()
			}
		}
		return super.onOptionsItemSelected(item)
	}

	/**
	 * Return the realm instance
	 */
	fun getRealm(): Realm {
		this.realm?.let {
			return it
		} ?: run {
			val realm = Realm.getDefaultInstance()
			this.realm = realm
			return realm
		}
	}

	/**
	 * Return if the location permission has been granted by the user
	 */
	fun hasLocationPermissionGranted(): Boolean {
		return ContextCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
	}

	/**
	 * Ask for location permission
	 */
	private fun askForLocationPermission(permissionCallback: ((granted: Boolean) -> Unit)) {
		this.permissionCallback = permissionCallback
		ActivityCompat.requestPermissions(
			this, arrayOf(ACCESS_FINE_LOCATION), PERMISSION_REQUEST_ACCESS_FINE_LOCATION
		)
	}

	/**
	 * Ask for places request
	 */
	fun askForPlacesRequest(callback: ((success: Boolean, places: ArrayList<PlaceLikelihood>) -> Unit)?) {
		// Call findCurrentPlace and handle the response (first check that the user has granted permission).
		if (ContextCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
			LocationManager(this).askForPlacesRequest(callback)
		} else {
			askForLocationPermission { granted ->
				if (granted) {
					LocationManager(this).askForPlacesRequest(callback)
				} else {
					callback?.invoke(false, ArrayList())
				}
			}
		}
	}

	/**
	 * Find the nearest location from the user
	 */
	fun findNearestLocation(callback: ((location: Location?) -> Unit)?) {
		if (LocationManager(this).databaseContainsLocationsWithCoordinates()) {
			if (ContextCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
				LocationManager(this).findNearestLocationFromUser(callback)
			} else {
				askForLocationPermission { granted ->
					if (granted) {
						LocationManager(this).findNearestLocationFromUser(callback)
					} else {
						callback?.invoke(null)
					}
				}
			}
		} else {
			callback?.invoke(null)
		}
	}

	/**
	 * Find the current location
	 */
	fun findCurrentLocation(callback: ((location: android.location.Location?) -> Unit)?) {
		if (ContextCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
			LocationManager(this).findCurrentLocation(callback)
		} else {
			askForLocationPermission { granted ->
				if (granted) {
					LocationManager(this).findCurrentLocation(callback)
				} else {
					callback?.invoke(null)
				}
			}
		}
	}

}