from IKImage import ImageManager, fenetre, canvas
import tkinter as Tk
import time
import random
import math

class Serpent2DDL:
    # Le serpent avec 2 segments et 2 degres de liberte
    def __init__(self):
        self.manager = ImageManager() # le manager d'images
        self.manager.ajouterImage('herbe') # fond en herbe (800x600 en 0,0)
        self.manager.ajouterImage('serpentCorps250') # corps du serpent uniquement (250x49)
        self.manager.setInitialPositionImage('serpentCorps250',50,520) # position du premier corps
        self.manager.setInitialRotationCenterPositionImage('serpentCorps250',0,24) # position du premier centre de rotation
        self.manager.setInitialNextRotationCenterPositionImage('serpentCorps250',250,24) # position du centre de rotation suivant
        self.setAngleCorps(0) # angle initial
        self.manager.ajouterImage('serpentCorps250Tete') # corps+tete du serpent (250x49)
        self.manager.setInitialPositionImage('serpentCorps250Tete',300,520) # position du deuxième corps
        self.manager.setInitialRotationCenterPositionImage('serpentCorps250Tete',0,24) # position du deuxième centre de rotation
        self.manager.setInitialNextRotationCenterPositionImage('serpentCorps250Tete',250,24) # position du centre suivant
        self.manager.setParentImage('serpentCorps250Tete','serpentCorps250') # le deuxieme corps est le parent du second
        self.setAngleTete(0) # angle initial
        self.manager.ajouterImage('pomme') # la pomme (50x50)
        self.manager.setInitialPositionImage('pomme',350,200) # position de la pomme (correspond a des angles d'environ 20 et 49 degre du serpent)

        # Interface utilisateur pour le serpent 2DDL
        # sliders pour les deux angles
        self.sliderAngleCorps = Tk.Scale(fenetre,from_=-180,to=180,orient=Tk.HORIZONTAL,command=self.changeAngleSliderCorps)
        self.sliderAngleCorps.place(x=800,y=0,width=200,height=50)
        self.sliderAngleCorps.set(0)
        self.sliderAngleTete = Tk.Scale(fenetre,from_=-180,to=180,orient=Tk.HORIZONTAL,command=self.changeAngleSliderTete)
        self.sliderAngleTete.place(x=800,y=50,width=200,height=50)
        self.sliderAngleTete.set(0)
        # clic pour placer la pomme
        fenetre.bind("<ButtonRelease-1>",self.clickPositionPomme)
        # bouton de recherche aleatoire
        self.buttonRechercheAleatoire = Tk.Button(fenetre,text="Recherche aleatoire",command=self.cherche_aleatoire)
        self.buttonRechercheAleatoire.place(x=800,y=100,width=200,height=50)
        # bouton de recherche analytique
        self.buttonRechercheAnalytique = Tk.Button(fenetre,text="Calcul analytique",command=self.calcul_analytique)
        self.buttonRechercheAnalytique.place(x=800,y=150,width=200,height=50)
        # bouton d'animation
        self.buttonAnimation = Tk.Button(fenetre,text="Animation",command=self.animation)
        self.buttonAnimation.place(x=800,y=200,width=200,height=50)
        # texte du statut
        self.textStatut = Tk.StringVar()
        self.labelStatut = Tk.Label(fenetre,textvariable=self.textStatut)
        self.labelStatut.place(x=800,y=550,width=200,height=50)
        self.textStatut.set("Cliquer sur un bouton de recherche")
        # lancement chronometre
        self.debutRecherche = time.time()

    def setAngleCorps(self,angle):
        # donne un angle au premier corps du serpent
        self.manager.setLocalOrientationImage('serpentCorps250',angle)
        self.manager.update()

    def setAngleTete(self,angle):
        # donne un angle au deuxième corps (corps+tete) du serpent
        self.manager.setLocalOrientationImage('serpentCorps250Tete',angle)
        self.manager.update()

    def update(self):
        # met a jour l'affichage et teste si la pomme est atteinte
        self.manager.update()
        if self.mangePomme():
            self.textStatut.set("Trouve en "+str(round(time.time() - self.debutRecherche,3))+" secondes")

    def mangePomme(self):
        # determine si la bouche est proche de la pomme
        posPomme = self.manager.getCenterPositionImage('pomme')
        posBouche = self.manager.getGlobalNextCenterPositionImage('serpentCorps250Tete')
        return posBouche.distance(posPomme) < 10

    def close(self):
        # fermeture des ressources du serpent
        self.manager.close()

    def changeAngleSliderCorps(self,value):
        # change l'angle du corps du serpent suite a un changement de placement du slider
        self.setAngleCorps(int(value))
        self.update()

    def changeAngleSliderTete(self,value):
        # change l'angle du corps+tete du serpent suite a un changement de placement du slider
        self.setAngleTete(int(value))
        self.update()

    def clickPositionPomme(self,event):
        # change la position de la pomme suite a un clic
        posxPommeFenetre = event.x_root-fenetre.winfo_rootx()
        posyPommeFenetre = event.y_root-fenetre.winfo_rooty()
        if posxPommeFenetre < 775:
            self.manager.setCenterPositionImage('pomme',posxPommeFenetre,posyPommeFenetre)
            self.update()

    def cherche_aleatoire(self):
        # cherche les angles du serpent de maniere aleatoire
        self.debutRecherche = time.time()
        iteration = 0

        # TODO : Donner une valeur assez grande a iteration_max
        iteration_max = 1

        while not self.mangePomme() and iteration < iteration_max:
            iteration += 1
            self.textStatut.set("En recherche aleatoire..."+str(iteration))

            # TODO : tirer aleatoirement deux valeurs pour les variables angleCorps et angleTete
            angleCorps = 0
            angleTete = 0

            self.setAngleCorps(angleCorps)
            self.setAngleTete(angleTete)
            self.sliderAngleCorps.set(angleCorps)
            self.sliderAngleTete.set(angleTete)
            self.update()
            fenetre.update()
        if iteration==iteration_max:
            self.textStatut.set("Nombre d'iterations max atteint")

    def calcul_analytique(self):
        # calcul l'angle du serpent 2DDL pour atteindre la pomme
        self.textStatut.set("En recherche analytique...")
        self.debutRecherche = time.time()

        # TODO : recuperation de la position de la pomme P
        # TODO : recuperation de la position du premier centre de rotation P1
        # TODO : calcul des angles angleCorps et angleTete avec les formules du sujet (Annexe A)
        # Vous aurez besoin des fonctions : math.atan2, math.sin, math.cos et math.acos
        angleCorps = 0
        angleTete = 0

        self.setAngleCorps(angleCorps)
        self.sliderAngleCorps.set(angleCorps)
        self.setAngleTete(angleTete)
        self.sliderAngleTete.set(angleTete)

        self.update()
        fenetre.update()

    def animation(self):
        i = 0
        while i < math.pi / 2:
            # deplace la pomme et demande au serpent de la suivre
            posPommex = 50+math.cos(i)*500
            posPommey = 544-math.sin(i)*500
            deltax = math.sin(i*8)*20
            deltay = -math.sin(i*8)*20
            self.manager.setCenterPositionImage('pomme',posPommex+deltax,posPommey+deltay)
            # calcul l'angle
            self.calcul_analytique()
            # mise a jour affichage
            self.update()
            fenetre.update()
            i += 0.01

s = Serpent2DDL()
fenetre.update()
fenetre.mainloop()
s.close()
