# -*- coding: utf-8 -*-

# Copyright 2009 Manik Bhattacharjee (manik-listes at altern.org)
#
# This file is part of PyVote.
#
# PyVote is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# PyVote is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with PyVote.  If not, see <http://www.gnu.org/licenses/>.


#
# Fonctions d'entrée-sortie pour les logiciels de scrutin et votes
#


# Imports nécessaires pour l'interface graphique
from PyQt4 import QtGui

#############################################
# Classe pour stocker le format Scrutin
# qui contient la description d'un scrutin
#############################################
class Scrutin:

  ### Fonction de lecture d'un fichier scrutin
  @staticmethod
  def read( filename = None ):

    h = {}
    if filename is None:
      filename = QtGui.QFileDialog.getOpenFileName ( None, "Charger un scrutin existant...")
      # Si l'utilisateur a annulé
      if filename is None or filename == "":
        return
    #Ouverture du fichier

    if isinstance(filename, file):
      print "already a file"
      f = filename
    else:
      print "just a filename"
      f = open(filename, 'r')

    #On vérifie que la première ligne est la bonne
    if eval(f.readline()) != "SCRUTIN FILE version 1.0":
            QtGui.QMessageBox.warning(None, u"Lecture Scrutin", u"Fichier "+unicode(filename)+u" invalide : en-tête incorrect !")
            return
    h["Header"] = "SCRUTIN FILE version 1.0"
    # Intitulé du scrutin
    h["Titre Scrutin"] = eval(f.readline().replace ( "\n", "" ))

    # Date de début
    h["Date Debut"] = eval(f.readline().replace ( "\n", "" ))
    # self.ui.dateDebut.setDateTime(QtCore.QDateTime.fromString(dt, QtCore.Qt.ISODate)) -> Conversion en QDateTime

    #Date de fin
    h["Date Fin"] = eval(f.readline().replace ( "\n", "" ))

    # type de scrutin
    h["Type Scrutin"] = eval(f.readline().replace ( "\n", "" ))

    # Données spécifiques du scrutin
    h["Parametres Scrutin"] = eval(f.readline().replace ( "\n", "" ))

    # Liste des électeurs
    h["Electeurs"] = eval(f.readline())

    # Liste des candidats
    h["Candidats"] = eval(f.readline())

    # Description détaillée
    h["Description Scrutin Html"] = eval(f.readline())

    # Dernière vérification
    if eval(f.readline()) != "SCRUTIN FILE version 1.0":
              QtGui.QMessageBox.warning(None, u"Lecture Scrutin", u"Fichier invalide : la dernière ligne est incorrecte !")
              return
    if not isinstance(filename, file):
      f.close()

    return h


  ### Fonction de sauvegarde d'un fichier Scrutin
  @staticmethod
  def write( h , filename = None ):
    if h["Header"] != "SCRUTIN FILE version 1.0":
      QtGui.QMessageBox.warning(None, u"Sauvegarde Scrutin", u"Données à sauver invalides (mauvais header) !")
      return
    if filename is None:
      filename = QtGui.QFileDialog.getSaveFileName ( None, "Enregistrer le scrutin")
      if filename is None or filename == "": # L'utilisateur a annulé -> on sort
            return

    # Création et ouverture du fichier
    if isinstance(filename, file):
      f = filename
    else:
      f = open(filename, 'w')

    # En-tête
    f.write(repr(h["Header"])+"\n")

    # Nom du scrutin
    f.write(repr(unicode(h["Titre Scrutin"]))+"\n")

    # Date de début
    f.write(repr(str(h["Date Debut"]))+"\n")
    # Date de fin
    f.write(repr(str(h["Date Fin"]))+"\n")

    # Type de scrutin
    f.write(repr(h["Type Scrutin"])+"\n")
    # Paramètres du scrutin
    f.write(repr(h["Parametres Scrutin"])+"\n")

    # Liste des électeurs
    f.write(repr(h["Electeurs"])+"\n")

    # Liste des candidats
    f.write(repr(h["Candidats"])+"\n")

    # Description détaillée
    f.write(repr(h["Description Scrutin Html"].replace ( "\n", " " )) + "\n")

    # Fin du fichier
    f.write(repr(h["Header"])+"\n")
    if not isinstance(filename, file):
      f.close()
    return True

#############################################
# Classe pour stocker le format Votes
# qui contient la description d'un scrutin
# ainsi qu'un ensemble de votes correspondant
# à ce scrutin, et un numéro d'urne
#############################################
class Votes:

  ### Fonction de lecture d'un fichier Votes
  @staticmethod
  def read( filename = None ):
    h = {}
    if filename is None:
      filename = QtGui.QFileDialog.getOpenFileName ( None, "Charger un fichier de votes existant...")
      # Si l'utilisateur a annulé
      if filename is None or filename == "":
        return

    #Ouverture du fichier
    if isinstance(filename, file):
      f = filename
    else:
      f = open(filename, 'r')

    print "Fichier ouvert"
    #On vérifie que la première ligne est la bonne
    if eval(f.readline()) != "VOTES FILE version 1.0":
            QtGui.QMessageBox.warning(None, u"Lecture Votes", u"Fichier "+unicode(filename)+u" invalide : en-tête incorrect !")
            return False

    print "Header OK"
    h["Header"] = "VOTES FILE version 1.0"

    # Intitulé du vote (exemple : Bureau 3 du département 19 elections regionales" et commentaires éventuels
    h["Titre Votes"] = eval(f.readline().replace ( "\n", "" ))
    h["Commentaires"] = eval(f.readline().replace ( "\n", "" ))

    # Identifiant de ce fichier de votes
    h["IdVotesFile"] = eval(f.readline().replace ( "\n", "" ))

    # Dates de début et de fin des votes enregistrés
    h["Date Debut"] = eval(f.readline().replace ( "\n", "" ))
    h["Date Fin"] = eval(f.readline().replace ( "\n", "" ))

    print "Debut de lecture du scrutin de titre "+h["Titre Votes"]+" et finissant le "+h["Date Fin"]

    # On lit les infos du scrutin (appel de la fonction correspondante)
    h["Scrutin"] = Scrutin.read(f)

    print "Scrutin ok"

    # Votes (un dictionnaire dont les clefs sont les ID de chaque vote et le contenu dépend du type de vote)
    h["Votes"] = eval(f.readline().replace ( "\n", "" ))

    # Dernière vérification
    if eval(f.readline()) != "VOTES FILE version 1.0":
              QtGui.QMessageBox.warning(None, u"Lecture Votes", u"Fichier invalide : la dernière ligne est incorrecte !")
              return
    if not isinstance(filename, file):
      f.close()

    return h



  ### Fonction de sauvegarde d'un fichier Votes
  @staticmethod
  def write( h, filename = None ):
    if h["Header"] != "VOTES FILE version 1.0":
      QtGui.QMessageBox.warning(None, u"Sauvegarde Votes", u"Données à sauver invalides (mauvais header) !")
      return False
    if filename is None:
      filename = QtGui.QFileDialog.getSaveFileName ( None, u"Enregistrer les votes")
      if filename is None or filename == "": # L'utilisateur a annulé -> on sort
            return False

    # Création et ouverture du fichier
    if isinstance(filename, file):
      f = filename
    else:
      f = open(filename, 'w')

    # En-tête
    f.write(repr(h["Header"])+"\n")

    # Nom du scrutin et commentaires
    f.write(repr(unicode(h["Titre Votes"]))+"\n")
    f.write(repr(unicode(h["Commentaires"]).replace ( "\n", "" ))+"\n")

    # Identifiant de ce fichier de votes
    f.write(repr(h["IdVotesFile"])+"\n")

    # Dates de début et de fin des votes enregistrés
    f.write(repr(str(h["Date Debut"]))+"\n")
    f.write(repr(str(h["Date Fin"]))+"\n")

    # Sauvegarde du scrutin
    Scrutin.write( h["Scrutin"], f)

    # Votes (un dictionnaire dont les clefs sont les ID de chaque vote et le contenu dépend du type de vote)
    # ATTENTION pour anonymiser, vérifier que ce n'est pas dans l'ordre d'enregistrement des votes,
    #           sinon les mettre dans l'ordre alphabétique.
    #k = h["Votes"].keys()
    #k.sort()
    f.write(repr(h["Votes"])+"\n")

    # Fin du fichier
    f.write(repr(h["Header"])+"\n")
    if not isinstance(filename, file):
      f.close()
    return True


#############################################
# Classe pour stocker la description d'un scrutin,
# le numéro de l'urne, et la liste des électeurs
# ayant voté dans cette urne
#############################################
class Registre:

  ### Lecture d'un fichier
  @staticmethod
  def read( filename = None ):
    h = {}
    if filename == None:
      filename = QtGui.QFileDialog.getOpenFileName ( None, "Charger un fichier registre existant...")
      # Si l'utilisateur a annulé
      if filename is None or filename == "":
        return

    #Ouverture du fichier
    if isinstance(filename, file):
      f = filename
    else:
      f = open(filename, 'r')

    #On vérifie que la première ligne est la bonne
    if eval(f.readline()) != "REGISTRE FILE version 1.0":
            QtGui.QMessageBox.warning(None, u"Lecture Registre", u"Fichier "+unicode(filename)+u" invalide : en-tête incorrect !")
            return
    h["Header"] = "REGISTRE FILE version 1.0"

    # Intitulé du vote (exemple : Bureau 3 du département 19 elections regionales" et commentaires éventuels
    h["Titre Votes"] = eval(f.readline().replace ( "\n", "" ))
    h["Commentaires"] = eval(f.readline().replace ( "\n", "" ))

    # Identifiant de ce fichier de votes
    h["IdVotesFile"] = eval(f.readline().replace ( "\n", "" ))

    # Dates de début et de fin des votes enregistrés
    h["Date Debut"] = eval(f.readline().replace ( "\n", "" ))
    h["Date Fin"] = eval(f.readline().replace ( "\n", "" ))

    # On lit les infos du scrutin (appel de la fonction correspondante)
    h["Scrutin"] = Scrutin.read(f)

    # Votes (un dictionnaire dont les clefs sont les ID de chaque vote et le contenu dépend du type de vote)
    h["Votants"] = eval(f.readline().replace ( "\n", "" ))

    # Dernière vérification
    if eval(f.readline()) != "REGISTRE FILE version 1.0":
              QtGui.QMessageBox.warning(None, u"Lecture Registre", u"Fichier invalide : la dernière ligne est incorrecte !")
              return
    if not isinstance(filename, file):
      f.close()

    return h


  ### Sauvegarde d'un registre de votes, qui liste les électeurs qui ont voté dans le fichier votes correspondant
  @staticmethod
  def write( h, filename = None ):
    if h["Header"] != "REGISTRE FILE version 1.0":
      QtGui.QMessageBox.warning(None, u"Sauvegarde Registre", u"Données à sauver invalides (mauvais header) !")
      return
    if filename is None:
      filename = QtGui.QFileDialog.getSaveFileName ( None, u"Enregistrer le registre des votes")
      if filename is None or filename == "": # L'utilisateur a annulé -> on sort
            return

    # Création et ouverture du fichier
    if isinstance(filename, file):
      f = filename
    else:
      f = open(filename, 'w')

    # En-tête
    f.write(repr(h["Header"])+"\n")

    # Nom du scrutin et commentaires
    f.write(repr(unicode(h["Titre Votes"]))+"\n")
    f.write(repr(unicode(h["Commentaires"]).replace ( "\n", "" ))+"\n")

    # Identifiant de ce fichier de votes
    f.write(repr(h["IdVotesFile"])+"\n")

    # Dates de début et de fin des votes enregistrés
    f.write(repr(str(h["Date Debut"]))+"\n")
    f.write(repr(str(h["Date Fin"]))+"\n")

    # Sauvegarde du scrutin
    Scrutin.write( h["Scrutin"], f)

    # Votes (un dictionnaire dont les clefs sont les ID de chaque vote et le contenu dépend du type de vote)
    # ATTENTION pour anonymiser, les noms sont enregistrés dans l'ordre alphabétique.
    h["Votants"].sort()
    f.write(repr(h["Votants"])+"\n")

    # Fin du fichier
    f.write(repr(h["Header"])+"\n")
    if not isinstance(filename, file):
      f.close()
    return True