"""
Mini-projet — Historique de navigateur, version orientée objet
================================================================

Ce fichier correspond à la partie 2 de la fiche « Piles et files avec
deque (mini-projet historique) ».

Il contient :
  - la classe Historique (constructeur, reculer, avancer, nouvelle_url,
    __repr__) ;
  - la création de trois objets indépendants, hist_A, hist_B, hist_C ;
  - un jeu d'instructions de test réparti sur ces trois objets ;
  - un test d'indépendance des objets (piège de l'argument mutable par
    défaut dans le constructeur).

Pour l'exécuter : télécharger ce fichier, puis dans un terminal, dans le
même dossier :
    python3 historique_navigateur_poo.py

Si tout est correct, le programme affiche "Tous les tests de la classe
Historique : OK".
"""

from collections import deque


class Historique:
    """Historique de navigation d'un onglet."""

    def __init__(self, url_actuelle, back=None, forward=None):
        self.back = deque(back) if back is not None else deque()
        self.current = url_actuelle
        self.forward = deque(forward) if forward is not None else deque()

    def reculer(self):
        """Modifie self : passe à la page précédente (sommet de back).
        Ne fait rien si back est vide."""
        if len(self.back) == 0:
            return
        self.forward.appendleft(self.current)
        self.current = self.back.pop()

    def avancer(self):
        """Modifie self : passe à la page suivante (sommet de forward).
        Ne fait rien si forward est vide."""
        if len(self.forward) == 0:
            return
        self.back.append(self.current)
        self.current = self.forward.popleft()

    def nouvelle_url(self, url):
        """Modifie self : visite une nouvelle page url, et vide forward."""
        self.back.append(self.current)
        self.current = url
        self.forward.clear()

    def __repr__(self):
        return f"Historique(back={list(self.back)}, current={self.current!r}, forward={list(self.forward)})"


def creer_trois_onglets():
    """Reconstruit les trois onglets de l'exemple, à chaque appel
    (pour que chaque test reparte d'objets neufs)."""
    hist_A = Historique('url_article1', back=['url_moteur', 'url_resultats1'], forward=[])
    hist_B = Historique('url_boite_reception', back=[], forward=['url_message_supprime'])
    hist_C = Historique('url_video1', back=['url_accueil_C'], forward=['url_video2', 'url_video3'])
    return hist_A, hist_B, hist_C


def test_jeu_instructions_trois_onglets():
    """Applique le jeu d'instructions réparti sur les trois onglets, et
    vérifie l'état final de chacun."""
    hist_A, hist_B, hist_C = creer_trois_onglets()

    hist_A.reculer()
    hist_B.avancer()
    hist_C.nouvelle_url('url_commentaires')
    hist_A.reculer()
    hist_B.nouvelle_url('url_nouveau_message')
    hist_C.reculer()
    hist_A.avancer()

    assert list(hist_A.back) == ['url_moteur'], "back de hist_A incorrect"
    assert hist_A.current == 'url_resultats1', "current de hist_A incorrect"
    assert list(hist_A.forward) == ['url_article1'], "forward de hist_A incorrect"

    assert list(hist_B.back) == ['url_boite_reception', 'url_message_supprime'], "back de hist_B incorrect"
    assert hist_B.current == 'url_nouveau_message', "current de hist_B incorrect"
    assert list(hist_B.forward) == [], "forward de hist_B incorrect"

    assert list(hist_C.back) == ['url_accueil_C'], "back de hist_C incorrect"
    assert hist_C.current == 'url_video1', "current de hist_C incorrect"
    assert list(hist_C.forward) == ['url_commentaires'], "forward de hist_C incorrect"

    print("Jeu d'instructions sur les trois onglets : OK")


def test_independance_des_objets():
    """Vérifie que modifier un objet Historique ne modifie pas un autre :
    c'est ce que garantit le constructeur avec back=None, forward=None
    par défaut (voir la fiche pour l'explication du piège évité)."""
    h1 = Historique('url_x')
    h2 = Historique('url_y')

    h1.nouvelle_url('url_z')

    assert list(h1.back) == ['url_x'], "back de h1 incorrect"
    assert h1.current == 'url_z', "current de h1 incorrect"
    assert list(h2.back) == [], "h2.back n'aurait pas dû être modifié par h1 !"
    assert h2.current == 'url_y', "h2.current n'aurait pas dû être modifié par h1 !"

    print("Indépendance des objets : OK")


if __name__ == "__main__":
    test_jeu_instructions_trois_onglets()
    test_independance_des_objets()
    print("Tous les tests de la classe Historique : OK")
