#!/usr/bin/python
# -*- coding:utf-8 -*-
# jeu de serpent

# BUG : on passe parfois sur des cerises sans les manger
# FIXME : creer une bombe qui explose sur ses 8 carres voisins au bout de 5 "delay"
# FIXME : creer un éléphant qui permet de passer au travers d'un mur
# FIXME : creer des trefles qui empechent les foods d'apparaitre (type "deco" ?)
# FIXME : creer une tonnelle qui cache ce qu'il y a en dessous (type "deco" ?)
# FIXME : mettre une langue/flamme a comportement a determiner (langue extensible sur demande pour aggripper la nourriture?)
# FIXME : avertir quand on n'a plus beaucoup d'energie (le serpent tire la langue)
# FIXME : ne pas reinitialiser completement le joueur : conserver le serpent, par ex.
# FIXME : changer la police de caractere
# TODO : faire un enchainement de niveaux
# TODO : 2e serpent !
# TODO : jeu en reseau

from items import *
from scores import *
import my_pygame_wrapper

########## play ##########
def treat_inputs(p1):
    # recuperer les evenements claviers/souris depuis le dernier appel
    direc_liste, pause_asked, quit_asked = my_pygame_wrapper.inputs()
    # on veut sortir
    if quit_asked :
        return "quit"
    # traiter les touches de direction
    while direc_liste != [] and not p1.snake.change_direc(direc_liste.pop()) :
        pass
    # on veut faire une pause
    if pause_asked :
        if my_pygame_wrapper.pause() == "quit":
            return "quit"

def foods_step(p1, walls, food, new_head):
    for f in food:
        forbidden_squares = [new_head] + walls.coord_list + p1.snake.coord_list
        for f2 in food :
            forbidden_squares += f2.coord_list
        f.step_forward(forbidden_squares)
    
def step_forward(p1, walls, food):
    new_head = p1.next_head()
    # tester si on meurt
    if walls.lay(new_head) or p1.lay(new_head):
        p1.explose()
    # on n'est pas mort
    else:
        # tester si on mange
        for f in food:
            if f.lay(new_head):                
                # maj nourriture
                f.eaten(p1, new_head)
                # maj joueur
                p1 = f.alter_player(p1)
    # traiter les food en attente
    foods_step(p1, walls, food, new_head)
    
    # tester si on vient de mourir
    if not p1.explosing() and p1.asphixie():
        p1.explose()
    # tester si on valide le niveau
    if p1.pass_level(p1):
        return "won"
    # tester si on n'a plus de vies
    if p1.dead():
        return "dead"
    # actualiser la position
    p1.move(new_head)
    return None

def display(p1, walls, food):
    my_pygame_wrapper.display_background()
    p1.display()
    walls.display()
    for f in food:
        f.display()
    my_pygame_wrapper.display_update()

def play():
    global current_level
    # initialiser les objets
    p1 = Player(current_level.SNAKE_CONFIG_INIT, \
                current_level.SNAKE_PARA, \
                current_level.PLAYER_CONFIG_INIT, \
                current_level.PLAYER_PARA, \
                current_level.player_pass_level, \
                current_level.player_note)
    walls = Wall(current_level.walls_coord_list)
    cherry1 = Cherry1(current_level.CHERRY1_DELAY, current_level.CHERRY1_WAITING, current_level.cherry1_effect)
    cherry2 = Cherry2(current_level.CHERRY2_DELAY, current_level.CHERRY2_WAITING, current_level.cherry2_effect)
    cherry3 = Cherry3(current_level.CHERRY3_DELAY, current_level.CHERRY3_WAITING, current_level.cherry3_effect)
    cherryminus = Cherryminus(current_level.CHERRYMINUS_DELAY, \
                                current_level.CHERRYMINUS_WAITING, \
                                current_level.cherryminus_effect)
    heart = Heart(current_level.HEART_DELAY, current_level.HEART_WAITING, current_level.heart_effect)
    egg = Egg(current_level.EGG_DELAY, current_level.EGG_WAITING, current_level.egg_effect)
    food = [cherry1, cherry2, cherry3, cherryminus, heart, egg]

    # les food commence 1 step avant les joueurs
    new_head = p1.next_head()
    foods_step(p1, walls, food, new_head)
    
    while True:
        # affichage
        display(p1, walls, food)
        # attendre
        my_pygame_wrapper.wait()
        # interpreter les commandes clavier/souris
        if treat_inputs(p1) == "quit":
            return "quit", -1
        # maj joueur et autres objets
        result = step_forward(p1, walls, food)
        if result == "dead":
            return "dead", -1
        elif result == "won":
            return "won", p1.note(p1)
########## end play ##########

def choose_level():
    global current_level
    message = [unicode("Choisissez le niveau :", "utf-8"), \
               unicode("[c] : mangez 60 cerises", "utf-8"), \
               unicode("[g] : montez votre énergie au maximum", "utf-8")]
    level_number = my_pygame_wrapper.input_box_display(message, 1)
    if level_number == "quit" :
        return "quit"
    current_level = set_level(level_number)
    while current_level == None :
        message = [unicode("Choisissez le niveau :", "utf-8"), \
                   unicode("[c] : mangez 60 cerises", "utf-8"), \
                   unicode("[g] : montez votre énergie au maximum", "utf-8"), \
                   unicode("Votre dernier choix était incorrect. Veuillez entrer une lettre.", "utf-8")]
        level_number = my_pygame_wrapper.input_box_display(message, 1)
        if level_number == "quit" :
            return "quit"
        current_level = set_level(level_number)
        
def run_one_game():
    global current_level
    
    def quitter():
        les_scores.register()

    les_scores = Scores_List(current_level.SCORES_FILE_NAME)
    while True:
        # choisir le niveau
        # FIXME : faire un sommaire dans level.py
        if choose_level() == "quit":
            quitter()
            return
        les_scores = Scores_List(current_level.SCORES_FILE_NAME)
        
        # afficher les objectifs du niveau choisi
        message = ['objectifs :'] + current_level.objectifs
        if my_pygame_wrapper.output_box_display(message) == "quit":
            quitter()
            return

        # jouer !
        result = play()
        if result[0] == "quit":
            quitter()
            return
        elif result[0] == "won": # objectifs atteints
            message = [unicode("Vous avez gagné %i points !" % result[1], "utf-8")]
            if les_scores.winner(result[1]): # meilleur score
                message += [unicode("Vous êtes dans les meilleurs scores !", "utf-8"), \
                            unicode("Entrez votre nom : ", "utf-8")]
                pseudo = my_pygame_wrapper.input_box_display(message, 10)
                if pseudo == "quit":
                    quitter()
                    return
                else :
                    les_scores.add(result[1], pseudo)
            else : # pas meilleur score
                message += [unicode("Vous n'êtes pas dans les meilleurs scores !", "utf-8")]
                if my_pygame_wrapper.output_box_display(message) == "quit":
                    quitter()
                    return
        else :
            message = [unicode("Vous n'avez pas atteint les objectifs !")]
            if my_pygame_wrapper.output_box_display(message) == "quit":
                quitter()
                return
        # afficher les meilleurs scores
        message = [unicode("Meilleurs scores pour ce niveau :", "utf-8")] + les_scores.consult()
        if my_pygame_wrapper.output_box_display(message) == "quit":
            quitter()
            return

        quitter()
        
def run():
    run_one_game()
    
# vrai quand le fichier est execute, et non importe en tant que module externe
if __name__ == "__main__":
    run()
