"""
NSI Archicture, Systèmes d'exploitation
Interblocage dans un robot.
"""

# Librairie utilisées
from threading import Thread
from threading import Lock
import time
import random

# Les ressources utilisées par le robot
R1_moteurs = Lock()
R2_wifi = Lock()
R3_camera = Lock()

# Variable partagée par les 3 threads
fin = False
compteur = 0


def P1_pilotage_manuel():
    """Fonction embarquée dans le thread P1"""
    global compteur
    while fin == False:
        print("P1 : demande de R1_moteurs...")
        R1_moteurs.acquire()
        print("P1 : demande de R2_wifi...")
        R2_wifi.acquire()
        print("P1 : début travail")
        time.sleep(random.random()/100.0)
        print("P1 : fin travail")
        compteur += 1
        print(f"*** {compteur} tâche(s) terminée(s)")
        print("P1 : libération de R1_moteurs...")
        R1_moteurs.release()
        print("P1 : libération de R2_wifi...")
        R2_wifi.release()


def P2_envoi_flux_video():
    """Fonction embarquée dans le thread P2"""
    global compteur
    while fin == False:
        print("P2 : demande de R2_wifi...")
        R2_wifi.acquire()
        print("P2 : demande de R3_camera...")
        R3_camera.acquire()
        print("P2 : début travail")
        time.sleep(random.random()/100.0)
        print("P2 : fin travail")
        compteur += 1
        print(f"*** {compteur} tâche(s) terminée(s)")
        print("P2 : libération de R2_wifi...")
        R2_wifi.release()
        print("P2 : libération de R3_camera...")
        R3_camera.release()


def P3_auto_tests_materiels():
    """Fonction embarquée dans le thread P3"""
    global compteur
    while fin == False:
        print("P3 : demande de R3_camera...")
        R3_camera.acquire()
        print("P3 : demande de R1_moteurs...")
        R1_moteurs.acquire()
        print("P3 : début travail")
        time.sleep(random.random()/100.0)
        print("P3 : fin travail")
        compteur += 1
        print(f"*** {compteur} tâche(s) terminée(s)")
        print("P3 : libération de R3_camera...")
        R3_camera.release()
        print("P3 : libération de R1_moteurs...")
        R1_moteurs.release()


if __name__ == '__main__':
    # Création des threads
    t1 = Thread(target=P1_pilotage_manuel)
    t2 = Thread(target=P2_envoi_flux_video)
    t3 = Thread(target=P3_auto_tests_materiels)

    # Lancement des threads
    t1.start()
    t2.start()
    t3.start()

    # Attente de la fin du travail
    t1.join()
    t2.join()
    t3.join()