// SPDX-FileCopyrightText: Adam Evyčędo
//
// SPDX-License-Identifier: GPL-3.0-or-later

package xyz.apiote.bimba.czwek.journeys

import android.content.Context
import android.content.Intent
import android.content.res.Configuration.UI_MODE_NIGHT_MASK
import android.content.res.Configuration.UI_MODE_NIGHT_UNDEFINED
import android.content.res.Configuration.UI_MODE_NIGHT_YES
import android.os.Build
import android.os.Bundle
import android.util.Log
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import org.osmdroid.tileprovider.tilesource.TileSourceFactory
import org.osmdroid.util.BoundingBox
import org.osmdroid.views.CustomZoomButtonsController
import org.osmdroid.views.overlay.TilesOverlay
import org.osmdroid.views.overlay.gestures.RotationGestureOverlay
import xyz.apiote.bimba.czwek.databinding.ActivityJourneysBinding
import xyz.apiote.bimba.czwek.dpToPixelI
import xyz.apiote.bimba.czwek.repo.Place
import kotlin.math.max
import kotlin.math.min

class JourneysActivity : AppCompatActivity() {
	private lateinit var binding: ActivityJourneysBinding

	companion object {
		const val ORIGIN_PARAM = "origin"
		const val DESTINATION_PARAM = "destination"

		fun getIntent(
			context: Context,
			origin: Place,
			destination: Place,
		) = Intent(context, JourneysActivity::class.java).apply {
			putExtra(ORIGIN_PARAM, origin)
			putExtra(DESTINATION_PARAM, destination)
		}
	}

	private fun getOrigin(): Place = if (Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU) {
		intent.getParcelableExtra(ORIGIN_PARAM, Place::class.java)
	} else {
		@Suppress("DEPRECATION")
		intent.getParcelableExtra(ORIGIN_PARAM)
	} ?: throw Exception("Origin not given")

	private fun getDestination(): Place = if (Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU) {
		intent.getParcelableExtra(DESTINATION_PARAM, Place::class.java)
	} else {
		@Suppress("DEPRECATION")
		intent.getParcelableExtra(DESTINATION_PARAM)
	} ?: throw Exception("Destination not given")

	override fun onCreate(savedInstanceState: Bundle?) {
		enableEdgeToEdge()
		super.onCreate(savedInstanceState)
		binding = ActivityJourneysBinding.inflate(layoutInflater)
		setContentView(binding.root)
		val journeysViewModel =
			ViewModelProvider(this)[JourneysViewModel::class.java]

		// TODO check upside-down
		// TODO for horizontal make side sheet
		ViewCompat.setOnApplyWindowInsetsListener(binding.journeys) { v, windowInsets ->
			val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
			v.updatePadding(bottom = insets.bottom + dpToPixelI(16f))
			WindowInsetsCompat.CONSUMED
		}

		binding.map.setTileSource(TileSourceFactory.MAPNIK)
		if (((resources?.configuration?.uiMode ?: UI_MODE_NIGHT_UNDEFINED)
					and UI_MODE_NIGHT_MASK) == UI_MODE_NIGHT_YES
		) {
			binding.map.overlayManager.tilesOverlay.setColorFilter(TilesOverlay.INVERT_COLORS)
		}
		binding.map.zoomController.setVisibility(CustomZoomButtonsController.Visibility.NEVER)
		binding.map.maxZoomLevel = 21.5
		binding.map.minZoomLevel = 5.5
		binding.map.setMultiTouchControls(true)
		binding.map.overlays.add(RotationGestureOverlay(binding.map).apply { isEnabled = true })

		binding.journeys.layoutManager = LinearLayoutManager(this)

		val origin = getOrigin()
		val destination = getDestination()

		journeysViewModel.journeys.observe(this) {
			zoomMap(100)
			binding.journeys.adapter = JourneysAdapter(layoutInflater, this, it) {
				// todo move map accordingly
				// todo show shape on map
			}
		}
		journeysViewModel.getJourneys(this, origin, destination)
	}

	override fun onStart() {
		super.onStart()
		zoomMap()
	}

	fun zoomMap(margin: Int = 0, box: BoundingBox? = null) {
		val origin = getOrigin()
		val destination = getDestination()
		val bb = box?:BoundingBox(
			max(origin.latitude, destination.latitude),
			max(origin.longitude, destination.longitude),
			min(origin.latitude, destination.latitude),
			min(origin.longitude, destination.longitude),
		)
		binding.map.zoomToBoundingBox(bb, false, margin)
	}
}