# Application web gérant les clients d'une maison d'édition

import os, cherrypy, sqlite3

# === Définition des gestionnaires de requetes HTTP ====

#################################################
#### Gestionnaire PRINCIPAL de l'application ####
#################################################

class HomePage(object):
    "Classe proposant un menu de gestion des clients d'une base de données"

    def __init__(self):
        # Les objets gestionnaires de requetes peuvent eux-memes
        # instancier d'autres gestionnaires "esclaves" et ainsi de suite

        self.recherche = RechercheClient()  # gestionnaire des recherches de clients
        self.ajout = AjouterClient()        # gestionnaire des ajouts de clients
        self.edition = EditionClient()      # gestionnaire d'édition de clients

        
    def index(self):
        """Retourne la page d'accueil de l'application web"""
        # Cherrypy invoquera cette méthode comme URL racine du site.
        # Sa valeur de retour sera la page web contenant le menu de
        # l'application Web dont le code HTML est situé dans un
        # fichier externe.

        # Récupération du code HTML du modèle de pages:
        fichier = open('annexes/modele.html', 'r', encoding = 'utf8')
        code = fichier.read()
        fichier.close()

        # Insertion du code HTML propre au menu de l'application:
        css = "annexes/MonStyle.css"
        title = "Menu de l'application"
        # Récupération du code de la page d'accueil
        accueil = open('annexes/accueil.html', 'r', encoding = 'utf8')
        content = accueil.read()
        accueil.close()
        content = content.format(gestionRecherche = "/recherche/", gestionAjout = '/ajout/')
        foot = "OCI, Collège du Sud"
        
        code = code.format(style = css, sousTitre = title, contenu = content, pied=foot)

        # Retourner le code HTML de la page demandée:
        return code

    index.exposed = True


##################################################
#### Gestionnaire de RECHERCHE et SUPPRESSION ####
##################################################

class RechercheClient(object):
    "Classe gérant la recherche et la suppression de clients"

    def index(self):
        "Retourne le formulaire permettant la recherche des clients"

        # code à compléter

        return """<p>Cette méthode gestionnaire de requetes affiche le formulaire de
        recherche basé sur le modèle annexes/formulaire.html formaté selon l'exemple-test</p>"""


 
    index.exposed = True
    

    def gestion(self, NomClient, AdresseClient, NoPostalClient, VilleClient, CantonClient):
        """Gère les requetes HTTP transmises par le formulaire de recherche de clients"""

        # code à compléter

        return """<p>Cette méthode gestionnaire de requete récupère
        les valeurs entrées dans le formulaire de recherche, fait une
        requete sur la base de données en vue de récupérer les
        enregistrements correspondant aux critères de recherche et les
        affiches dans un tableau HTML à l'aide de la méthode <em>html_from_sql_result</em>.</p>"""

                      
    gestion.exposed = True

    def suppression(self, toDelete=None):
        """Supprime les enregistrements sélectionnés dans le tableau des
        résultats d'une recherche. Les identifiants des enregistrements à
        supprimer se trouvent dans la liste <toDelete> récupérée en argument."""

        # code à compléter

        return """<p>Cette méthode supprime les enregistrements
        sélectionnés dans le tableau des résultats d'une recherche.
        Les identifiants des enregistrements à supprimer se trouvent
        dans la liste <toDelete> récupérée en argument. Notons que le
        paramètre <toDelete> sera de type <None> si aucun
        enregistrement n'a été précédemment sélectionné, de type <str>
        si un seul élément a été sélectionné et de type <list> si
        plusieurs éléments ont été sélectionnés.  </p>"""

    suppression.exposed = True



    def html_from_sql_result(self, cursor):
        """
        Retourne le code HTML affichant les enregistrements situés dans le curseur <cursor>
        sous la forme d'un tableau
        """
        # Récupération de tous les enregistrements du curseur sous forme de liste d'objets Row
        enregistrements = cursor.fetchall()

        try:
            # Récupération de la liste des noms de champs
            nomAttributs = enregistrements[0].keys()
        
        except:
            code = '<p> La recherche n\'a retourné aucun résultat.</p>'

        else:

            # en-tête du tableau en tant qu'élément de la classe css .sqlResultHeader
            table_header = '<tr class ="sqlResultHeader"><th>{donnees}</th></tr>\n'\
                           .format(donnees='</th><th>'.join(nomAttributs))

            # corps du tableau: les lignes sont des éléments de la classe css .rowclass0 ou .rowclass1
            # selon leur position dans la table (=> alternance de couleurs des lignes)
            table_enregistrements = ''
            row_index = 0

            for e in enregistrements:

                # récupération des valeurs des attributs associés à l'enregistrement traité
                valeurs = []
                for champ in nomAttributs:
                    valeurs.append(str(e[champ]))

                # construction de la ligne du tableau associée à l'enregistrement traité
                elements = '</td><td>'.join(valeurs)     
                table_enregistrements += '<tr class = "rowclass{index}"><td>{donnees}</td></tr>\n'.format(index=row_index, donnees=elements)
                row_index = (row_index + 1) % 2         # moduler l'index de la ligne pour assurer l'alternance des couleurs

            code = '<table>\n {entete} \n {contenu} \n</table>\n'\
                    .format(entete=table_header, contenu=table_enregistrements)

        return code

################################
#### Gestionnaire d'EDITION ####
################################   

class EditionClient(object):
    "Classe gérant l'édition de clients"

    def __init__(self):
        "Définit l'identifiant de l'enregistrement en cours de mise à jour"

        self.id = 0 # l'identifiant du client traité est initialisé à
                    # 0 mais sera modifié à chaque invocation de la méthode index


    def index(self, identifiant=0):
        """
        Permet de modifier les données d'un client à partir de son <identifiant>
        """

        # code à compléter

        return """<p>Cette méthode gestionnaire de requete récupère
        l'identifiant du client dont il faut modifier des données,
        fait une requete sur la base de données afin de récupérer
        toutes les données actuelles du client et crée un formulaire
        contenant ses données sur la base du fichier
        annexes/formulaireEdition.html. Les modifications apportées au
        client via le formulaire seront traitées par une autre méthode
        de gestion </p>"""

    index.exposed = True

    def gestion(self, NomClient, AdresseClient, NoPostalClient, VilleClient, CantonClient):
        """Gère les requetes HTTP transmises par le formulaire d'édition de clients"""

        # code à compléter

        return """<p>Cette méthode gère les données transmises par le
        formulaire d'édition en faisant une mise à jour du client
        traité dans la base de données selon les données entrées dans
        le formulaire</p>"""
    
        
    gestion.exposed = True


##############################
#### Gestionnaire d'AJOUT ####
##############################


class AjouterClient(object):
    "Classe gérant l'ajout de clients"
    
    def index(self):
        "Retourne le formulaire permettant l'ajout d'un client"

        # code à compléter

        return """<p>Cette méthode gestionnaire de requetes affiche le
        formulaire d'ajout de clients basé sur le modèle
        annexes/formulaire.html formaté selon l'exemple-test</p>"""

    index.exposed = True

    def gestion(self, NomClient, AdresseClient, NoPostalClient, VilleClient, CantonClient):
        """Gère les requetes HTTP transmises par le formulaire d'ajout de clients"""

        # code à compléter

        return """<p>Cette méthode gère les données entrées dans le
        formulaire de rajout. Si tous les champs ont été remplis, la
        méthode transmet leur valeur dans la base de données. Sinon,
        elle retourne un message d'erreur à l'utilisateur.</p>"""

               
    gestion.exposed = True


# === PROGRAMME PRINCIPAL ====

# Reconfiguration et démarrage du serveur web :
cherrypy.config.update({"tools.staticdir.root":os.getcwd()})
cherrypy.quickstart(HomePage(), config='tutoriel.conf')
        
