#!/bin/bash /usr/scripts/python.sh
# -*- coding: utf-8 -*-

u"""
Copyright (C) Valentin Samir
Licence : GPLv3

"""
import sys
import time
import ldap
import traceback
if '/usr/scripts' not in sys.path:
    sys.path.append('/usr/scripts')

from gestion.affich_tools import coul
import gestion.config as config

import lc_ldap.objets as objets
import lc_ldap.attributs as attributs

import lc
from CPS import TailCall, tailcaller, Continue
from CPS import unicode_of_Error

class Dialog(lc.Dialog):

    @tailcaller
    def edit_blacklist_select(self, obj, title, cont):
        """
        Permet de choisir une blackliste parmis celle de obj oubien une nouvelle blacklist.
        Retourne (index, bl) où bl est un dictionnaire représentant la blackliste et index
        l'index de la blackliste dans obj['blacklist'] ou new pour une nouvelle blacklist
        """
        def box():
            choices = [('new', 'Ajouter une nouvelle blackliste')]
            index = 0
            for bl in obj['blacklist']:
                choices.append(
                   (str(index),
                     coul("%s [%s]" % (bl['type'], bl['comm']), 'rouge' if bl['actif'] else None,
                     dialog=True)
                   )
                )
                index+=1
            return self.dialog.menu(
                "Éditer une blacklist ou en ajouter une nouvelle ?\n(les blacklistes actives apparaissent en rouge)",
                width=0,
                timeout=self.timeout,
                height=0,
                menu_height=0,
                item_help=0,
                title=title,
                scrollbar=True,
                colors=True,
                cancel_label="Retour",
                backtitle=self._connected_as(),
                choices=choices)

        def todo(tag):
            if tag == 'new':
                return tag, {'debut':0, 'fin':0, 'type':'', 'comm':''}
            else:
                bl = {}
                bl.update(obj['blacklist'][int(tag)].value)
                return tag, bl


        (code, tag) = self.handle_dialog(cont, box)
        retry_cont = TailCall(self.edit_blacklist_select, obj=obj, title=title, cont=cont)
        return self.handle_dialog_result(
            code=code,
            output=tag,
            cancel_cont=cont,
            error_cont=retry_cont,
            codes_todo=[([self.dialog.DIALOG_OK], todo, [tag])]
        )

    @tailcaller
    def edit_blacklist_type(self, title, cont):
        """Permet de choisir un type de blackliste pour les nouvelles blacklistes"""
        retry_cont = TailCall(self.edit_blacklist_type, title=title, cont=cont)

        def box():
            return self.dialog.menu(
                "Choisissez un type de blacklist",
                width=0,
                height=0,
                menu_height=0,
                item_help=0,
                timeout=self.timeout,
                title=title,
                scrollbar=True,
                colors=True,
                cancel_label="Retour",
                backtitle=self._connected_as(),
                choices=[(k,v) for (k,v) in config.blacklist_items.items()])

        def todo(tag, retry_cont):
            if tag in config.blacklist_items:
                return tag
            else:
                 self.dialog.msgbox("%s n'est pas une blacklist" % tag, timeout=self.timeout,
                    title="Erreur rencontrée", width=73, height=10)
                 raise Continue(retry_cont)

        (code, tag) = self.handle_dialog(cont, box)
        return self.handle_dialog_result(
            code=code,
            output=tag,
            cancel_cont=cont(bl=None),
            error_cont=retry_cont,
            codes_todo=[([self.dialog.DIALOG_OK], todo, [tag, retry_cont])]
        )


    def edit_blacklist(self, obj, title, update_obj, cont, bl=None, tag=None, bl_type=None,
                       debut=None, fin=None, comm=None):
        """Pour éditer les blacklistes d'un objet lc_ldap"""
        self_cont = TailCall(self.edit_blacklist, obj=obj, title=title, update_obj=update_obj,
                            cont=cont, bl=bl, tag=tag, bl_type=bl_type, debut=debut, fin=fin, comm=comm)
        # Si bl ou tag ne sont pas définit on les demande
        if bl is None or tag is None:
            bl_type = None
            debut = None
            fin = None
            comm = None
            tag, bl = self.edit_blacklist_select(obj, title, cont(**{update_obj:obj}))
        if bl_type is None and tag == 'new':
            bl['type'] = self.edit_blacklist_type(title, self_cont(obj=obj))
        elif tag == 'new':
            bl['type'] = bl_type

        # Cas de l'ajout d'un blacklist
        if tag == 'new':
            # Si debut n'est pas encore spécifié, on le demande
            if debut is None:
                 debut_tuple = self.get_timestamp(title=title, text="Choisir le début de la blacklist",
                          cont=self_cont(bl=bl, tag=tag, bl_type=None, debut=None, fin=None, comm=None))
                 debut = int(time.mktime(time.struct_time(debut_tuple + (0, 0, -1))))
            # Idem pour fin
            if fin is None:
                if self.dialog.yesno("Mettre une date de fin ?", title=title,
                                       timeout=self.timeout) == self.dialog.DIALOG_OK:
                    fin_tuple = self.get_timestamp(title=title, text="Choisir la date de fin :",
                                                   cont=self_cont(bl=bl, tag=tag, bl_type=bl_type,
                                                   debut=None, fin=None, comm=None))
                    fin = int(time.mktime(time.struct_time(debut_tuple + (0, 0, -1))))
                else:
                    fin = '-'
            bl['debut']=debut
            bl['fin']=fin
            bl['comm']=self.get_comment(title=title, text="Commentaire ?",
                  cont=self_cont(bl=bl, tag=tag, bl_type=bl['type'], debut=debut, fin=None, comm=None))
            if self.confirm_item(item=attributs.attrify(bl, 'blacklist', self.conn),
                        title="Ajouter la blacklist ?"):
                try:
                    with self.conn.search(dn=obj.dn, scope=0, mode='rw')[0] as obj:
                        obj['blacklist'].append(bl)
                        obj.validate_changes()
                        obj.history_gen()
                        obj.save()
                    # On s'en va en mettant à jour dans la continuation la valeur de obj
                    raise Continue(self_cont(bl=None, obj=obj))
                # On propage les Continue
                except self.error_to_raise:
                    raise
                # En cas d'une autre erreur, on l'affiche et on retourne
                except (Exception, ldap.OBJECT_CLASS_VIOLATION) as e:
                     self.dialog.msgbox(traceback.format_exc() if self.debug_enable else ("%s" % unicode_of_Error(e)), timeout=self.timeout,
                        title="Erreur rencontrée", width=73)
                     raise Continue(self_cont(obj=obj))
            else:
                raise Continue(self_cont(bl=None, obj=obj))

        # Cas de l'édition d'une blacklist
        else:
            if debut is None:
                # Mettre un warning pour éditer (seulement quand debut vaut None pour ne pas le répéter à chaque fois que l'on revient en arrière par la suite
                if not self.confirm_item(item=attributs.attrify(bl, 'blacklist', self.conn), title="Éditer la blackliste ?"):
                    raise Continue(self_cont(bl=None, obj=obj))
                debut = time.localtime(bl['debut'])
                debut_tuple = self.get_timestamp(title=title, text="Choisir le début de la blacklist", cont=self_cont(bl=bl, tag=tag, debut=None, fin=None, comm=None),
                   day=debut.tm_mday,
                   month=debut.tm_mon,
                   year=debut.tm_year,
                   hour=debut.tm_hour,
                   minute=debut.tm_min,
                   second=debut.tm_sec
                )
                debut = int(time.mktime(time.struct_time(debut_tuple + (0, 0, -1))))
            bl['debut'] = debut
            if fin is None:
                if self.dialog.yesno("Mettre une date de fin ?", timeout=self.timeout, title=title) == self.dialog.DIALOG_OK:
                    if bl['fin'] == '-':
                        fin = time.localtime()
                    else:
                        fin = time.localtime(bl['fin'])
                    fin_tuple = self.get_timestamp(title=title, text="Choisir la date de fin :", cont=self_cont(bl=bl, tag=tag, debut=debut, fin=None, comm=None),
                       day=fin.tm_mday,
                       month=fin.tm_mon,
                       year=fin.tm_year,
                       hour=fin.tm_hour,
                       minute=fin.tm_min,
                       second=fin.tm_sec
                    )
                    fin = int(time.mktime(time.struct_time(debut_tuple + (0, 0, -1))))
                else:
                    fin = '-'
            bl['fin'] = fin
            bl['comm']=self.get_comment(title=title, text="Commentaire ?", init=bl['comm'], cont=self_cont(bl=bl, tag=tag, bl_type=bl['type'], debut=debut, fin=None, comm=None))
            if self.confirm_item(item=attributs.attrify(bl, 'blacklist', self.conn), title="Modifier la blacklist ?"):
                try:
                    with self.conn.search(dn=obj.dn, scope=0, mode='rw')[0] as obj:
                        obj['blacklist'][int(tag)]=bl
                        obj.validate_changes()
                        obj.history_gen()
                        obj.save()
                    # On s'en va en mettant à jour dans la continuation la valeur de obj
                    raise Continue(self_cont(bl=None, obj=obj))
                # On propage les Continue
                except self.error_to_raise:
                    raise
                # En cas d'une autre erreur, on l'affiche et on retourne au menu d'édition
                except (Exception, ldap.OBJECT_CLASS_VIOLATION) as e:
                     self.dialog.msgbox(traceback.format_exc() if self.debug_enable else "%s" % unicode_of_Error(e), timeout=self.timeout, title="Erreur rencontrée", width=73)
                     raise Continue(self_cont)
            else:
                raise Continue(self_cont(bl=None, obj=obj))
