package it.danieleverducci.openweddingapp.ui.location

import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.content.ContextCompat
import androidx.core.text.HtmlCompat
import androidx.fragment.app.Fragment
import androidx.preference.PreferenceManager
import com.android.volley.VolleyError
import com.squareup.picasso.Picasso
import it.danieleverducci.openweddingapp.BuildConfig
import it.danieleverducci.openweddingapp.Config
import it.danieleverducci.openweddingapp.R
import it.danieleverducci.openweddingapp.databinding.FragmentLocationBinding
import it.danieleverducci.openweddingapp.entities.LocalizedLocation
import it.danieleverducci.openweddingapp.entities.Location
import it.danieleverducci.openweddingapp.networking.LocationNet
import it.danieleverducci.openweddingapp.networking.StaticItemNet
import it.danieleverducci.openweddingapp.utils.PackageUtils
import it.danieleverducci.openweddingapp.utils.SharedPreferencesManager
import org.osmdroid.config.Configuration
import org.osmdroid.util.GeoPoint
import org.osmdroid.views.overlay.Marker
import java.lang.RuntimeException
import java.util.*

class LocationFragment : Fragment() {
    companion object {
        private val TAG = "LocationFragment"
    }
    private lateinit var binding: FragmentLocationBinding

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding = FragmentLocationBinding.inflate(inflater, container, false)

        // Setup map
        val osmdroidConfig = Configuration.getInstance()
        osmdroidConfig.load(
            context,
            PreferenceManager.getDefaultSharedPreferences(requireContext())
        )
        osmdroidConfig.userAgentValue = BuildConfig.APPLICATION_ID
        binding.map.setMultiTouchControls(true)
        binding.map.setTilesScaledToDpi(true)

        loadLocation()

        return binding.getRoot()
    }

    /**
     * Loads location from shared preferences, if any.
     * Then, tries to update location from static online service.
     */
    fun loadLocation() {
        // Load from cache
        val location = SharedPreferencesManager.loadLocation(requireContext())
        fillPageWith(location)

        // Load/update from net
        LocationNet(requireContext()).getItem(object: StaticItemNet.OnItemObtainedListener<Location> {
            override fun OnItemObtained(item: Location) {
                if(item.version > location.version) {
                    fillPageWith(item)
                    binding.locationProgress.visibility = View.GONE
                    binding.locationContainer.visibility = View.VISIBLE
                    SharedPreferencesManager.saveLocation(requireContext(), item)
                    Log.d(TAG, "Updated location: local ${location.version}, remote ${item.version}")
                } else {
                    Log.d(TAG, "Location up to date: local ${location.version}, remote ${item.version}")
                }
            }

            override fun OnError(error: VolleyError) {
                binding.locationProgress.visibility = View.GONE
                Log.d(TAG, "Unable to update location: ${error}")
            }
        })
    }

    fun fillPageWith(loc: Location) {
        val location: LocalizedLocation
        if (loc.localized.containsKey(Locale.getDefault().language))
            location = loc.localized.get(Locale.getDefault().language)!!
        else if (loc.localized.containsKey(Config.STATIC_CONTENT_DEFAULT_LOCALE))
            location = loc.localized.get(Config.STATIC_CONTENT_DEFAULT_LOCALE)!!
        else
        throw RuntimeException("Missing default locale ${Config.STATIC_CONTENT_DEFAULT_LOCALE} in location json!")

        // Image
        Picasso.get()
            .load(location.pictureUrl)
            .error(R.drawable.placeholder)
            .into(binding.image)

        // Text
        binding.name.text = location.name
        binding.content.text = HtmlCompat.fromHtml(location.content, HtmlCompat.FROM_HTML_MODE_LEGACY)

        // Map
        updateViewCoords(location)

        // Navigation button
        binding.navigate.setOnClickListener {
            // Generate geouri intent
            val i = Intent()
            i.action = Intent.ACTION_VIEW
            i.data = if (PackageUtils.isGoogleMapsInstalled(requireContext())) location.gooleMapsUri else location.geoUri
            startActivity(i)
        }
    }

    fun updateViewCoords(item: LocalizedLocation) {
        // Center map
        val position = GeoPoint(item.coordinates[0], item.coordinates[1])
        val mapController = binding.map.controller
        mapController.setZoom(15.0)
        mapController.setCenter(position)

        // Set pin
        val mapMarker = Marker(binding.map)
        mapMarker.setPosition(position)
        val drawable = AppCompatResources.getDrawable(
            requireContext(),
            R.drawable.ic_map_pin
        )
        if (android.os.Build.VERSION.SDK_INT >= 21)
            drawable!!.setTint(ContextCompat.getColor(requireContext(), R.color.colorAccent))
        mapMarker.setIcon(drawable)
        mapMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM)
        binding.map.overlays.add(mapMarker)
    }
}