import requests
import json
import os
import time
from multiprocessing import Pool, cpu_count

# Paramètres globaux
MIN_LAT, MAX_LAT = 41.0, 51.0
MIN_LON, MAX_LON = -5.0, 8.0
RESOLUTION = 0.000003  # Environ 30 cm
BATCH_SIZE = 175
MAX_FILE_SIZE = 2 * 1024 * 1024  # 2 Mo
SECTIONS_FILE = 'sections.json'
STATE_FILE = 'progress_state.json'

def generate_sections(lat_step=0.1, lon_step=0.1):
	"""Génère une liste de sections couvrant la France avec affichage de la progression."""
	sections = []
	total_steps = int((MAX_LAT - MIN_LAT) / lat_step) * int((MAX_LON - MIN_LON) / lon_step)
	completed_steps = 0
	
	lat = MIN_LAT
	while lat < MAX_LAT:
		lon = MIN_LON
		while lon < MAX_LON:
			sections.append((lat, lon))
			lon += lon_step
			completed_steps += 1
			percentage = (completed_steps / total_steps) * 100
			print(f"Progression de la création des sections : {percentage:.2f}%")
		lat += lat_step
	return sections

def save_sections(sections):
	"""Sauvegarde les sections dans un fichier JSON."""
	with open(SECTIONS_FILE, 'w') as f:
		json.dump(sections, f)
	print(f"Sections saved to {SECTIONS_FILE}")

def load_sections():
	"""Charge les sections à partir du fichier JSON."""
	if os.path.exists(SECTIONS_FILE):
		with open(SECTIONS_FILE, 'r') as f:
			sections = json.load(f)
	else:
		sections = generate_sections()
		save_sections(sections)
	return sections

def req(longitude, latitude):
	"""Envoie une requête à l'API pour obtenir les altitudes."""
	longi = "|".join(map(str, longitude))
	latti = "|".join(map(str, latitude))
	
	url = f'https://wxs.ign.fr/calcul/alti/rest/elevation.json?lon={longi}&lat={latti}&zonly=true'
	
	while True:
		try:
			response = requests.get(url)
			if response.status_code == 200:
				data = response.json()
				if 'elevations' in data:
					return data['elevations']
				else:
					print("Impossible d'obtenir l'altitude pour les coordonnées spécifiées.")
					return []
			else:
				print(f"Erreur de réponse de l'API. Code de statut : {response.status_code}")
				time.sleep(1)
		except requests.exceptions.RequestException as e:
			print(f"Une erreur s'est produite lors de la requête : {e}")
			time.sleep(1)

def is_section_in_france(lat, lon):
	"""Vérifie si une section est en France en testant les altitudes aux quatre coins."""
	coords = [
		(lat, lon),
		(lat + 0.1, lon),
		(lat, lon + 0.1),
		(lat + 0.1, lon + 0.1)
	]
	for coord in coords:
		elevation = req([coord[1]], [coord[0]])
		if elevation and elevation[0] == -99999.0:
			return False
	return True

def filter_sections_in_france(sections):
	"""Filtre les sections pour ne conserver que celles en France."""
	total_sections = len(sections)
	valid_sections = []
	for i, section in enumerate(sections):
		if is_section_in_france(section[0], section[1]):
			valid_sections.append(section)
		percentage = (i + 1) / total_sections * 100
		print(f"Progression de la vérification des sections : {percentage:.2f}%")
	save_sections(valid_sections)
	return valid_sections

def process_section(section):
	"""Récupère les altitudes pour une section donnée avec une résolution fine."""
	lat, lon = section
	data = []

	current_lat = lat
	while current_lat < lat + 0.1 and current_lat < MAX_LAT:
		current_lon = lon
		while current_lon < lon + 0.1 and current_lon < MAX_LON:
			latitudes = [current_lat]
			longitudes = [current_lon]
			new_data = req(longitudes, latitudes)
			if new_data:
				data += new_data
			current_lon += RESOLUTION
		current_lat += RESOLUTION

	return data

def save_section(data, file_index):
	"""Sauvegarde les données dans un fichier JSON."""
	filename = f'data_part_{file_index}.json'
	with open(filename, 'w') as f:
		json.dump(data, f)
	print(f"Data saved to {filename}")

def load_progress():
	"""Charge l'état du programme à partir du fichier d'état."""
	if os.path.exists(STATE_FILE):
		with open(STATE_FILE, 'r') as f:
			state = json.load(f)
	else:
		state = {
			"current_section_index": 0,
			"file_index": 0
		}
	return state

def save_state(state):
	"""Sauvegarde l'état du programme dans un fichier d'état."""
	with open(STATE_FILE, 'w') as f:
		json.dump(state, f)

def process_and_save(section, file_index):
	"""Traite une section et sauvegarde le résultat."""
	data = process_section(section)
	if data:
		save_section(data, file_index)
		file_index += 1
	return file_index

def main():
	sections = load_sections()
	sections = filter_sections_in_france(sections)
	state = load_progress()

	current_section_index = state["current_section_index"]
	file_index = state["file_index"]

	total_sections = len(sections)
	num_cores = max(1, cpu_count() - 1)  # Utiliser tous les cœurs sauf un pour le parallélisme local

	while current_section_index < total_sections:
		end_index = min(current_section_index + num_cores, total_sections)
		sections_to_process = sections[current_section_index:end_index]
		
		with Pool(num_cores) as pool:
			results = pool.starmap(process_and_save, [(section, file_index) for section in sections_to_process])
		
		# Mettre à jour file_index
		file_index = max(results)

		current_section_index = end_index

		# Mettre à jour l'état
		state["current_section_index"] = current_section_index
		state["file_index"] = file_index
		save_state(state)

if __name__ == "__main__":
	main()
	# Vérification des versions installées
	import requests
	import urllib3

	print("Requests version:", requests.__version__)
	print("Urllib3 version:", urllib3.__version__)
