from davistk import *
from time import sleep

# dimensions du jeu
hauteur_pong = 100
largeur_pong = 10
largeur_fenetre = 640
hauteur_fenetre = 480
distance_pong_bord = 30
rayon_balle = 10


def affiche_balle(position_balle):
    """ Ne pas modifier. Affiche un cercle correspondant à la balle à la
    position position_balle où position_balle est un couple (tuple) de
    coordonnées.
    Parameters:
        position_balle (int,int): couple des coordonnées de la balle
    """
    x, y = position_balle
    cercle(x, y, rayon_balle, "black", "black")


def affiche_pong(position_pong, droite_gauche):
    """ Ne pas modifier. Affiche un rectangle correspondant à la raquette
    centré à la position position_pong où position_pong est l'ordonnée de la
    position de la raquette.
    Peut afficher la raquette à gauche ou à droite en fonction du
    paramètre droite_gauche
    Parameters:
        position_pong (int): ordonnée de la raquette
        droite_gauche (str): prend les valeurs "gauche" ou "droite" en
        fonction de la raquette à afficher
    """
    if droite_gauche == "gauche":
        x = distance_pong_bord
    else:
        x = largeur_fenetre - distance_pong_bord
    y = position_pong
    rectangle(x - largeur_pong / 2, y - hauteur_pong / 2, x + largeur_pong / 2, y+hauteur_pong / 2, "black", "black")


def mouvement_ordi(position_balle, position_pong1):
    """ Ne pas modifier, gère le déplacement de l'ordinateur """
    x, y = position_balle
    if y > position_pong1 + hauteur_pong / 4:
        return position_pong1 + 5
    elif y < position_pong1 - hauteur_pong / 4:
        return position_pong1 - 5
    else:
        return position_pong1


def detection_impact_pong(position_pong1, position_pong2, position_balle, direction_balle):
    """ Ne pas modifier. Fonction permettant de détecter l'impact entre une
    raquette et la balle et changeant la direction de celle-ci """
    x, y = position_balle
    dx, dy = direction_balle
    x_pong1, y_pong1 = distance_pong_bord, position_pong1
    x_pong2, y_pong2 = largeur_fenetre - distance_pong_bord, position_pong2
    balle_sur_pong1 = y < y_pong1 + hauteur_pong / 2 and y > y_pong1 - hauteur_pong / 2 and x - rayon_balle < x_pong1 + largeur_pong / 2 and x - rayon_balle > x_pong1 - largeur_pong / 2
    balle_sur_pong2 = y < y_pong2 + hauteur_pong / 2 and y > y_pong2 - hauteur_pong / 2 and x + rayon_balle < x_pong2 + largeur_pong / 2 and x + rayon_balle > x_pong2 - largeur_pong / 2
    if balle_sur_pong1:
        return -dx, dy + (y - y_pong1)/100
    if balle_sur_pong2:
        return -dx, dy + (y - y_pong2)/100
    return dx, dy


def deplacement_balle(position_balle, direction_balle):
    ''' Ne pas modifier. Permet de calculer la nouvelle position de la balle à partir de
    sa position initiale et de la direction (mouvement) dans laquelle elle va.
    Parameters:
        position_balle (float, float): couple de coordonnées de la balle
        direction_balle (float, float): couple de déplacement à ajouter aux
        coordonnées
    Returns:
        (float, float): nouvelles coordonnées de la balle
    '''
    x, y = position_balle
    dx, dy = direction_balle
    return x + dx, y + dy


def change_direction_pong2(touche):
    """ Retourne le déplacement de la raquette en ordonnée (en pixel).
    Si la touche appuyée est "Up" alors retourne -5
    Si la touche appuyée est "Down" alors retourne 5
    Sinon retourne 0
    Parameters:
        touche (str): nom de la touche pressée
    Returns:
        (int): déplacement en ordonnée de la raquette
    """
    return 0  # à modifier


def detection_bord(position_balle, direction_balle):
    """ Permet de détecter l'impact de la balle sur le bord supérieur
    ou inférieur de la fenêtre. Renvoie la nouvelle direction de la balle
    Parameters:
        position_balle (float, float): couple des coordonnées de la balle
        direction_balle(float, float): couple correspondant à la vitesse
        horizontale et verticale de la balle
    Returns:
        (float, float): couple correspondant à la vitesse horizontale
        et verticale de la balle après impact éventuel avec le bord.
    """
    x, y = position_balle  # récupère l'abscisse et l'ordonnée de la balle
    dx, dy = direction_balle  # récupère la direction de la balle suivant les
    # les abscisses et suivant les ordonnées
    return dx, dy  # à modifier


def detection_sortie(position_balle):
    ''' Permet de détecter la sortie de la balle d'un côté ou d'un autre.
    Renvoie la chaine de caractère "pong1" si la balle sort à gauche, "pong2"
    elle sort à droite, "continue" sinon.
    Parameters:
        position_balle (float, float): couple des coordonnées de la
        balle_sur_pong1
    Returns:
        (string): "pong1" si la balle sort à gauche, "pong2"
        elle sort à droite, "continue" sinon
    '''
    x, y = position_balle  # récupère l'abscisse et l'ordonnée de la balle
    return "continue"  # à modifier


def deplacement_pong(position_pong, direction_pong):
    ''' Permet de calculer la nouvelle position d'une raquette à partir de
    sa position initiale et de la direction (mouvement) dans laquelle elle va.
    Parameters:
        position_pong (int): ordonnée de la raquette
        direction_pong (int): déplacement à ajouter à l'ordonnée
    Returns:
        (int): nouvelle ordonnée de la raquette
    '''
    return position_pong  # à modifier


def fin_de_jeu(sortie):
    ''' Permet de sortir de la boucle principale du jeu.
    Parameters:
        sortie (str): information de sortie d'un côté ("pong1), de l'autre
        ("pong2") ou de non sortie ("continue")
    Returns:
        (bool): True si la balle est sortie, False sinon
    '''
    return False  # à modifier


def affiche_victoire(sortie):
    ''' Fonction permettant de gérer graphiquement la fin de jeu
    Parameters:
        sortie (str): information de sortie d'un côté ("pong1), de l'autre
        ("pong2") ou de non sortie ("continue")
    Returns:
        ...
    '''
    ...  # à modifier


# programme principal
if __name__ == "__main__":
    # initialisation du jeu
    framerate = 20    # taux de rafraîchissement du jeu en images/s
    direction_balle = (5, 0.5)  # direction initiale de la balle
    position_balle = (320, 240)  # position initiale de la balle
    position_pong1 = 240
    position_pong2 = 240
    cree_fenetre(largeur_fenetre, hauteur_fenetre)

    # boucle principale
    jouer = True
    while jouer:
        # affichage des objets
        efface_tout()  # efface tous les objets
        affiche_pong(position_pong1, "gauche")  # affiche la raquette gauche
        affiche_pong(position_pong2, "droite")  # affiche la raquette gauche
        affiche_balle(position_balle)  # affiche la balle
        mise_a_jour()  # met à jour l'affichage

        direction_pong2 = 0  # remet le mouvement du pong de droite à 0

        # gestion des événements
        ev = donne_ev()  # récupère les évènements clavier ou souris
        ty = type_ev(ev)  # récupère le type d'événement
        if ty == 'Quitte':
            break
        elif ty == 'Touche':  # Si c'est un événement clavier
            # print(touche(ev))
            direction_pong2 = change_direction_pong2(touche(ev))
        position_pong1 = mouvement_ordi(position_balle, position_pong1)
        position_pong2 = deplacement_pong(position_pong2, direction_pong2)
        direction_balle = detection_impact_pong(position_pong1, position_pong2, position_balle, direction_balle)
        direction_balle = detection_bord(position_balle, direction_balle)
        sortie = detection_sortie(position_balle)
        position_balle = deplacement_balle(position_balle, direction_balle)
        jouer = not fin_de_jeu(sortie)
        # attente avant rafraîchissement
        sleep(1/framerate)

    # Affichage fin de jeu
    affiche_victoire(sortie)
    # fermeture et sortie
    ferme_fenetre()
