#!/bin/bash /usr/scripts/python.sh
# -*- coding: utf-8 -*-
#
# stats_cableurs.py
# -----------------
#
# Copyright (C) 2013-2015 Raphaël-David Lasseri <lasseri@crans.org>,
#                         Pierre-Elliott Bécue <becue@crans.org>,
#
# This file 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 2 of the License, or
# (at your option) any later version.
#
# This file 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 this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
"""
Ce script permet de se faire mousser en listant les câbleurs et leurs
stats.
"""

import sys
import datetime
import argparse

import lc_ldap.shortcuts as shortcuts
import lc_ldap.crans_utils as crans_utils
import gestion.config as config
import gestion.affichage as affichage

from cranslib.decorators import static_var
from config import ann_scol


### Appels à LDAP et tri initial sur l'année en cours.
DB = shortcuts.lc_ldap_readonly()
SCORES = []
HISTORIQUE = []
ENCODING = config.out_encoding

@static_var(("data", []))
def adherents(regen=False):
    """Fonction évaluée paresseusement pour retourner la liste des
    adhérents"""

    if regen or not adherents.data:
        adherents.data = DB.search(u'(&(debutAdhesion>=%s)(aid=*))' % (crans_utils.to_generalized_time_format(config.debut_periode_transitoire)), sizelimit=2000)
    return list(adherents.data)

@static_var(("data", []))
def factures(regen=False):
    """Fonction évaluée paresseusement pour retourner la liste des câbleurs"""

    if regen or not factures.data:
        factures.data = DB.search(u'(&(|(debutAdhesion>=%(now)s)(debutConnexion>=%(now)s))(fid=*))' % {
            'now': crans_utils.to_generalized_time_format(config.debut_periode_transitoire),
        }, sizelimit=4000)
    return list(factures.data)

@static_var(("data", []))
def cableurs(regen=False):
    """Fonction évaluée paresseusement pour retourner la liste des
    câbleurs"""

    if regen or not cableurs.data:
        cableurs.data = DB.search(u'(|(droits=cableur)(droits=nounou)(droits=bureau))')
    return list(cableurs.data)

#### On prends les historiques de tout les adhérents
def parse_historique(ligne):
    """Parse une ligne d'historique et renvoie [ligne parsée],action
    du cableur, date de l'action"""
    champ = ligne.value.replace(',', '').replace(':', '').split(' ', 3)
    sdate = champ[0].split('/')
    date = datetime.date(int(sdate[2]), int(sdate[1]), int(sdate[0]))
    champ_action = champ[3]
    return (champ, champ_action, date)

def actions_cableurs():
    """Renvoie l'historique de tous les adherents et tri en fonction
    des actions éffectuées."""
    for adherent in adherents():
        histo = adherent.get('historique', [])
        for histo_line in histo:
            champ = parse_historique(histo_line)[0]
            champ_action = parse_historique(histo_line)[1]
            date = parse_historique(histo_line)[2]
            if (u' inscription' in champ_action or u'Adhesion+' in champ_action) and date > datetime.date(ann_scol, 8, 1):
                HISTORIQUE.append(champ)

    for facture in factures():
        histo = facture.get('historique', [])
        for histo_line in histo:
            champ = parse_historique(histo_line)[0]
            champ_action = parse_historique(histo_line)[1]
            date = parse_historique(histo_line)[2]
            if u'controle' in champ_action and date > datetime.date(ann_scol, 8, 1):
                HISTORIQUE.append(champ)
    return HISTORIQUE

#### On parse l'historique et on trie
def score_cableurs():
    """Calcul le score de tout les câbleurs en fonction des actions
    effectuées """
    for cableur in cableurs():
        inscriptions = reinscriptions = controles = 0
        nom = cableur.get(u'nom', None)[0].value
        prenom = cableur.get(u'prenom', None)[0].value
        uid = cableur.get(u'uid', None)[0].value
        for index in range (0, len(HISTORIQUE)):
            histo_uid = HISTORIQUE[index][2]
            histo_action = HISTORIQUE[index][3]
            if histo_uid == uid and histo_action == u' inscription':
                inscriptions += 1
            if histo_uid == uid and (u"debutAdhesion+" in histo_action):
                reinscriptions += 1
            if histo_uid == uid and (u"controle" in histo_action):
                controles += 1
        score = 2*inscriptions + reinscriptions + controles
        SCORES.append(["%s %s" % (prenom, nom), score, inscriptions, reinscriptions, controles])
    return SCORES

### Tri par score
def sort_by_score():
    """Tri la liste des câbleurs par ordre de score décroissant de score"""
    return score_cableurs().sort(key=lambda x:int(x[1]), reverse=True)

def sort_by_inverse_score():
    """Tri la liste des câbleurs par ordre de score croissant de score"""
    return score_cableurs().sort(key=lambda x:int(x[1]))

def cableurs_utiles():
    """Renvoi le nombre de cableurs ayant un score non nul"""
    useless_cableurs = 0
    for k in range(0, len(cableurs())):
        if (SCORES[k][1] == 0):
            useless_cableurs = useless_cableurs + 1
    return len(cableurs()) - useless_cableurs


#### Affichage ou x est le nombre de câbleurs à afficher
def show_all(limit, swap):
    """Tableau fait main pour un effet plus visuel"""
    titre = [u"Câbleur", u"Score", u"Inscriptions", u"Réinscriptions", u"Contrôles"]
    largeur = [25, 8, 16, 16, 16]
    alignement = ["c", "c", "c", "c", "c"]
    data = [[elem for elem in SCORES[index]] for index in xrange(limit)]
    total = [0]*4
    for elem in SCORES:
        total = [total[i] + elem[i+1] for i in xrange(len(total))]
    total = [["Total"] + total]
    print affichage.tableau(data, titre=titre, largeur=largeur, alignement=alignement, swap=swap).encode(ENCODING)
    print affichage.tableau(total, titre=titre, largeur=largeur, alignement=alignement, swap=swap).encode(ENCODING)

#### On définit le Parser
if __name__ == "__main__":
    actions_cableurs()

    PARSER = argparse.ArgumentParser()
    PARSER.add_argument("-a", "--all", help="Affiche les scores de tout les câbleurs", action="store_true")
    PARSER.add_argument("-t", "--top", help="Affiche seulement les meilleurs câbleurs", action="store_true")
    PARSER.add_argument("-s", "--scores", help="Affiche seulement les câbleurs ayant un score non nul", action="store_true")
    PARSER.add_argument("-m", "--menage", help="Affiche seulement les câbleurs ayant un score nul", action="store_true")
    PARSER.add_argument("-n", "--nocolour", help="Désactive la couleur", action="store_true")
    ARGS = PARSER.parse_args()


    if ARGS.nocolour:
        SWAP = []
    else:
        SWAP = [None, "vert"]

    if ARGS.all:
        sort_by_score()
        show_all(len(cableurs()), swap=SWAP)
    elif ARGS.scores:
        sort_by_score()
        show_all(cableurs_utiles(), swap=SWAP)
    elif ARGS.menage:
        sort_by_inverse_score()
        show_all(len(cableurs()) - cableurs_utiles(), swap=SWAP)
    elif ARGS.top:
        sort_by_score()
        show_all(5, swap=SWAP)
    else:
        sort_by_score()
        show_all(10, swap=SWAP)
    print affichage.style(u"""stats_cableurs n'est pas un jouet, ni un outil
pour comparer qui de deux membres actifs a fait le plus de
câblages. C'est un outil qui sert au conseil d'administration
et aux nounous pour le suivi.

De plus, l'utiliser à tort et à travers occasionne de la charge
sur la base de données des adhérents, que le script doit aller
lire pour afficher les résultats.

Merci d'user de ce script avec parcimonie, et de ne pas jouer à
"qui à la plus grosse".""", ['rouge']).encode(ENCODING)
