package com.example.tp8;

import android.content.Intent;
import android.location.Address;
import android.location.Geocoder;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.activity.EdgeToEdge;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.exifinterface.media.ExifInterface;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Locale;

public class MainActivity extends AppCompatActivity {

    private ImageView imageView;
    private TextView latiTextView;
    private TextView longiTextView;
    private TextView locationTextView;
    private Button loadImageButton;
    private Button showLocationButton;
    private Button findNearbyPhotosButton; // Exo3
    private double[] currentLatLong;

    // Result launcher pour gérer la récupération et l'affichage de l'image choisie
    private final ActivityResultLauncher<String> getImageLauncher = registerForActivityResult(
            new ActivityResultContracts.GetContent(), // Récupérer le chemin de l'image
            uri -> {
                if (uri != null) { // S'il y a bien une image
                    imageView.setImageURI(uri); // L'afficher sur son emplacement
                    showExifData(uri); // Puis récupérer les coords GPS si possible
                }
            }
    );

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_main);
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
            Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
            return insets;
        });

        imageView = findViewById(R.id.imageView); // Récupération des éléments de l'interface
        latiTextView = findViewById(R.id.lati);
        longiTextView = findViewById(R.id.longi);
        locationTextView = findViewById(R.id.location);
        loadImageButton = findViewById(R.id.button_load_image);
        showLocationButton = findViewById(R.id.button_show_location); // Bouton caché au lancement, affiché si des coords GPS sont trouvées
        findNearbyPhotosButton = findViewById(R.id.button_find_nearby_photos); // Bouton exo3
        Button findPhotosByUserLocationButton = findViewById(R.id.button_find_photos_by_user_location); // Bouton exo4


        loadImageButton.setOnClickListener(event -> { // Quand le bouton de chargement est utilisé
            getImageLauncher.launch("image/*");  // On lance la demande d'image
        });

        showLocationButton.setOnClickListener(event -> {
            if (currentLatLong != null) {
                reverseGeocode(currentLatLong[0], currentLatLong[1]); // GPS -> Lieu
            }
        });

        findNearbyPhotosButton.setOnClickListener(event -> {
            if (currentLatLong != null) {
                Intent intent = new Intent(MainActivity.this, PhotoListActivity.class);
                intent.putExtra("referenceLatLong", currentLatLong); // Passer les coordonnées de la photo actuelle
                startActivity(intent);
            }
        });

        findPhotosByUserLocationButton.setOnClickListener(event -> {
            Intent intent = new Intent(MainActivity.this, NearbyPhotosActivity.class);
            startActivity(intent);
        });
    }

    private void showExifData(Uri imageUri) { // Fonction qui extrait les coords GPS
        try (InputStream inputStream = getContentResolver().openInputStream(imageUri)) {
            // J'essaie de récupérer les données de l'image
            if (inputStream != null) {
                ExifInterface exifInterface = new ExifInterface(inputStream); // Permet d'intéragir avec l'image
                currentLatLong = exifInterface.getLatLong(); // Obtenir les coordonnées
                if (currentLatLong != null) { // Si les coords sont bien définies https://developer.android.com/reference/android/media/ExifInterface#getLatLong(float[])
                    latiTextView.setText(getString(R.string.lati) + " " + currentLatLong[0]); // Je peux les écrire
                    longiTextView.setText(getString(R.string.longi) + " " + currentLatLong[1]);
                    showLocationButton.setVisibility(View.VISIBLE); // Afficher le bouton pour trouver le lieu
                    findNearbyPhotosButton.setVisibility(View.VISIBLE); // Afficher le bouton pour trouver les photos proches
                } else {
                    latiTextView.setText(getString(R.string.lati) + " Inconnue"); // Sinon, inconnu
                    longiTextView.setText(getString(R.string.longi) + " Inconnue");
                    showLocationButton.setVisibility(View.GONE); // Cacher le bouton pour trouver le lieu
                    findNearbyPhotosButton.setVisibility(View.GONE); // Cacher le bouton pour trouver les photos proches
                }
                locationTextView.setText(""); // Retirer le lieu affiché
            }
        } catch (IOException e) { // En cas de problème avec la récupération de l'image ou ses données
            e.printStackTrace(); // J'affiche l'erreur
            latiTextView.setText(getString(R.string.lati) + " Erreur");
            longiTextView.setText(getString(R.string.longi) + " Erreur");
            showLocationButton.setVisibility(View.GONE);
            findNearbyPhotosButton.setVisibility(View.GONE);
        }
    }

    private void reverseGeocode(double latitude, double longitude) {
        // DOC: https://developer.android.com/reference/android/location/Geocoder
        new Thread(() -> { // Pour ne pas bloquer l'application, je lance la récupération dans un sous-processus
            Geocoder geocoder = new Geocoder(this, Locale.getDefault());
            try {
                List<Address> addresses = geocoder.getFromLocation(latitude, longitude, 1); // J'essaie de récupérer 1 adresse qui correspond
                if (addresses != null && !addresses.isEmpty()) { // Si l'on a trouvé quelque chose
                    Address address = addresses.get(0);
                    StringBuilder addressText = new StringBuilder(); // Je prépare une String
                    if (address.getLocality() != null) { // Si j'ai la bille
                        addressText.append(address.getLocality()).append(", "); // J'ajoute à la String
                    }
                    if (address.getCountryName() != null) {
                        addressText.append(address.getCountryName()); // Idem pour le pays
                    }
                    // https://stackoverflow.com/a/11140342 pour retourner les données vers le thread principal
                    runOnUiThread(() -> locationTextView.setText(addressText.toString())); // Et je retourne ça au thread principal
                } else {
                    runOnUiThread(() -> locationTextView.setText(getString(R.string.unknown_place))); // Pas d'adresse trouvée
                }
            } catch (IOException e) {
                e.printStackTrace(); // Crash
                runOnUiThread(() -> locationTextView.setText(getString(R.string.error_place)));
            }
        }).start();
    }
}