import pygame
import math
import random  # à importer tout en haut si ce n’est pas déjà fait


# Paramètres graphiques
LARGEUR, HAUTEUR = 1000, 1000
FPS = 60

# Paramètres physiques (Lune)
G = 6.674e-11          # Constante universelle (toujours la même)
M = 5.972e24                # Masse de l'astre central (kg)
R = 6.371e6                # Rayon de l'astre central (m)
altitude = 3.844e8 - R         # Altitude de l'objet en orbite (m)
rayon_orbite = R + altitude  # Rayon orbital total (m)

# Échelle de conversion (pixels/mètre)
ECHELLE = (LARGEUR / 2 - 50) / rayon_orbite

pygame.init()
fenetre = pygame.display.set_mode((LARGEUR, HAUTEUR))
pygame.display.set_caption("Simulation d'orbite autour de la Lune")
clock = pygame.time.Clock()
font = pygame.font.SysFont("Arial", 16)


def convertir_secondes(secondes):
    jours = int(secondes // (24 * 3600))
    reste = secondes % (24 * 3600)
    heures = int(reste // 3600)
    reste %= 3600
    minutes = int(reste // 60)
    sec = int(reste % 60)
    return f"{jours:02d}j {heures:02d}h {minutes:02d}m {sec:02d}s"


def calcul_orbite(G, M, rayon_orbite, temps):
    # Calcule vitesse orbitale et position

    # Ecris tes calculs ici
    v = math.sqrt((G*M)/rayon_orbite)
    w = v/rayon_orbite
    x = rayon_orbite * math.cos(w * temps)
    y = rayon_orbite * math.sin(w * temps)
    
    return x, y, v, w

def dessiner_ligne_pointillee(surface, couleur, depart, arrivee, longueur=5, espace=5):
    x1, y1 = depart
    x2, y2 = arrivee
    dx = x2 - x1
    dy = y2 - y1
    distance = math.hypot(dx, dy)
    nb_segments = int(distance // (longueur + espace))
    for i in range(nb_segments):
        start_x = x1 + (dx / distance) * (i * (longueur + espace))
        start_y = y1 + (dy / distance) * (i * (longueur + espace))
        end_x = x1 + (dx / distance) * (i * (longueur + espace) + longueur)
        end_y = y1 + (dy / distance) * (i * (longueur + espace) + longueur)
        pygame.draw.line(surface, couleur, (start_x, start_y), (end_x, end_y))


def main():
    running = True
    temps = 0
    facteur_acceleration = 90000  # Pour visualiser l'orbite plus vite

    periode_orbitale = 2 * math.pi * math.sqrt(rayon_orbite**3 / (G * M))
    centre_x, centre_y = LARGEUR // 2, HAUTEUR // 2

    x0, y0, _, _ = calcul_orbite(G, M, rayon_orbite, 0)
    satellite_x0 = centre_x + int(x0 * ECHELLE)
    satellite_y0 = centre_y + int(y0 * ECHELLE)

    trajectoire = []  # Liste des positions successives du satellite

    marqueurs = []  # Liste des points placés chaque jour
    dernier_jour = -1  # Pour détecter les changements de jour

    # Champ d’étoiles avec scintillement
    etoiles = []
    nb_etoiles = 300
    for _ in range(nb_etoiles):
        x = random.randint(0, LARGEUR)
        y = random.randint(0, HAUTEUR)
        taille = random.randint(1, 2)
        luminosite = random.randint(120, 255)
        variation = random.choice([-1, 1])
        etoiles.append([x, y, taille, luminosite, variation])

    while running:
        clock.tick(FPS)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False

        temps += (1/FPS) * facteur_acceleration

        x, y, vitesse_orbitale, omega = calcul_orbite(G, M, rayon_orbite, temps)

        # Vérifier si un jour entier est passé
        jour_actuel = int(temps // 86400)
        if jour_actuel != dernier_jour:
            dernier_jour = jour_actuel
            # Stocker la position du satellite à ce moment-là
            marqueur_x = centre_x + int(x * ECHELLE)
            marqueur_y = centre_y + int(y * ECHELLE)
            marqueurs.append((marqueur_x, marqueur_y, jour_actuel))

        satellite_x = centre_x + int(x * ECHELLE)
        satellite_y = centre_y + int(y * ECHELLE)
        trajectoire.append((satellite_x, satellite_y))

        if len(trajectoire) > 127:
            trajectoire.pop(0)

        # Affichage
        fenetre.fill((0, 0, 0))  # Espace sombre

        # Dessin du champ d’étoiles avec scintillement
        for etoile in etoiles:
            x, y, taille, lum, sens = etoile

            # Mettre à jour la luminosité
            lum += sens * random.randint(0, 3)  # variation douce et irrégulière

            # Inverser le sens si on atteint les limites
            if lum >= 255:
                lum = 255
                sens = -1
            elif lum <= 100:
                lum = 100
                sens = 1

            # Mémoriser la nouvelle valeur
            etoile[3] = lum
            etoile[4] = sens

            # Dessiner l’étoile
            couleur = (lum, lum, lum)
            pygame.draw.circle(fenetre, couleur, (x, y), taille)

        # Ligne pointillée depuis le centre jusqu'à la position initiale du satellite
        dessiner_ligne_pointillee(fenetre, (100, 100, 100), (centre_x, centre_y), (satellite_x0, satellite_y0))

        # Dessiner les marqueurs de changement de jour
        for mx, my, num_jour in marqueurs:
            pygame.draw.circle(fenetre, (255, 255, 255), (mx, my), 3)
            texte_jour = font.render(str(num_jour), True, (255, 255, 255))
            fenetre.blit(texte_jour, (mx + 5, my - 10))

        rayon_affichage = max(int(R * ECHELLE), 10)  # minimum visuel
        
        for i, (x, y) in enumerate(trajectoire):
            # Calcul de la transparence et du rayon en fonction de l'ancienneté
            alpha = int(127 * (i / len(trajectoire)))  # 0 → 255
            rayon = max(1, int(3 * (i / len(trajectoire))))  # 1 à 3 pixels

            couleur = (alpha, alpha, 127)  # du bleu clair à blanc bleuté
            pygame.draw.circle(fenetre, couleur, (x, y), rayon)
            
        pygame.draw.circle(fenetre, (200, 200, 200), (centre_x, centre_y), rayon_affichage)
        pygame.draw.circle(fenetre, (255, 255, 255), (satellite_x, satellite_y), 5)  # Satellite

        # Orbite tracée
        pygame.draw.circle(fenetre, (60, 60, 60), (centre_x, centre_y), int(rayon_orbite * ECHELLE), 1)

        # Affichage des infos
        temps_txt = convertir_secondes(temps)
        jours_simules = int(temps // 86400)
        periode_txt = convertir_secondes(periode_orbitale)

        infos = [
            f"Temps simulé : {temps_txt}",
            f"Jours simulés : {jours_simules}",
            f"Période orbitale : {periode_txt}",
            f"Altitude orbite : {altitude/1000:.0f} km",
            f"Vitesse orbitale : {vitesse_orbitale:.1f} m/s",
            f"Vitesse angulaire : {omega:.5f} rad/s",
            f"Accélération du temps : x{facteur_acceleration}"
        ]

        for i, texte in enumerate(infos):
            surface_texte = font.render(texte, True, (255, 255, 255))
            largeur_texte, hauteur_texte = surface_texte.get_size()
            fenetre.blit(surface_texte, (LARGEUR - largeur_texte - 10, 10 + i*(hauteur_texte + 5)))

        pygame.display.flip()

    pygame.quit()

if __name__ == "__main__":
    main()
