# -*- coding: utf-8 -*-
import os
from django.test import TestCase, Client
from django.contrib.auth.models import User
from coin.members.models import Member, LdapUser, LdapGroup
import logging


class MemberTests(TestCase):
        
    def test_when_creating_member_a_ldapuser_is_also_created_with_same_data(self):
        """
        Test que lors de la création d'un nouveau membre, une entrée 
        correspondante est bien créée dans le LDAP et qu'elle contient 
        les mêmes données.
        Cela concerne le nom et le prénom
        """
        #~ Créé un membre
        
        first_name = u'Gérard';
        last_name = u'Majax';
        ldap_cn =  MemberTestsUtils.get_random_ldap_cn()
        member = Member(first_name = first_name,
                        last_name = last_name,
                        ldap_cn = ldap_cn)
        member.save()
        
        #~ Récupère l'utilisateur LDAP et fait les tests
        ldap_user = LdapUser.objects.get(pk=ldap_cn)
        
        self.assertEqual(ldap_user.first_name, first_name)
        self.assertEqual(ldap_user.last_name, last_name)
        self.assertEqual(ldap_user.pk, ldap_cn)
        
        member.delete();
        ldap_user.delete();
    
    def test_when_modifiying_member_corresponding_ldap_user_is_also_modified_with_same_data(self):
        """
        Test que lorsque l'on modifie un membre, l'utilisateur LDAP 
        correspondant est bien modifié
        Cela concerne le no met le prénom
        """
        #~ Créé un membre
        first_name = u'Ronald';
        last_name = u'Mac Donald';
        ldap_cn =  MemberTestsUtils.get_random_ldap_cn()
        member = Member(first_name = first_name, last_name = last_name, ldap_cn = ldap_cn)
        member.save()
        
        #~  Le modifie
        new_first_name = u'José';
        new_last_name = u'Bové';
        member.first_name = new_first_name
        member.last_name = new_last_name
        member.save()
        
        #~ Récupère l'utilisateur LDAP et fait les tests
        ldap_user = LdapUser.objects.get(pk=ldap_cn)
        
        self.assertEqual(ldap_user.first_name, new_first_name)
        self.assertEqual(ldap_user.last_name, new_last_name)

        member.delete();
        ldap_user.delete();
    
    def test_when_creating_member_corresponding_ldap_user_is_in_coin_ldap_group(self):
        """
        Test que l'utilisateur Ldap fraichement créé est bien dans le group "coin"
        Et que lors de la supression d'un membre, l'utilisateur LDAP correspondant 
        est bien retiré du groupe.
        """
        #~ Créé un membre
        ldap_cn =  MemberTestsUtils.get_random_ldap_cn()
        member = Member(first_name = 'Canard', last_name = 'WC', ldap_cn = ldap_cn)
        member.save()
        
        #~ Récupère le group "coin" et test que l'utilisateur y est présent
        ldap_group = LdapGroup.objects.get(pk="coin")
        self.assertEqual(ldap_cn in ldap_group.members, True)
        
        #~ Supprime l'utilisateur
        member.delete();
        
        #~ Récupère le group "coin" et test que l'utilisateur n'y est plus
        ldap_group = LdapGroup.objects.get(pk="coin")
        self.assertEqual(ldap_cn in ldap_group.members, False)
        
        LdapUser.objects.get(pk=ldap_cn).delete();


    def test_change_password_and_auth(self):
        """
        Test que la fonction change_password de member fonctionne et permet
        l'authentification avec le nouveau mot de passe
        """
        ldap_cn = MemberTestsUtils.get_random_ldap_cn()
        password = "1234"
        
         #~ Créé un nouveau membre
        member = Member(first_name = u'Passe-partout', last_name = u'Du fort Boyard', ldap_cn = ldap_cn)
        member.save()
        
        #~ Récupère l'utilisateur LDAP
        ldap_user = LdapUser.objects.get(pk=ldap_cn)
        
        #~ Change son mot de passe
        member.change_password(password)

        #~ Test l'authentification
        c = Client()
        self.assertEqual(c.login(username=ldap_cn, password=password), True)
        
        member.delete();
        ldap_user.delete();


    def test_when_creating_member_ldap_display_name_is_well_defined(self):
        """
        Lors de la création d'un membre, le champ "display_name" du LDAP est 
        prenom + nom
        """
        first_name = u'Gérard'
        last_name = u'Majax'
        ldap_cn = MemberTestsUtils.get_random_ldap_cn()
        member = Member(first_name = first_name, last_name = last_name, ldap_cn = ldap_cn)
        member.save()
        
        #~ Récupère l'utilisateur LDAP
        ldap_user = LdapUser.objects.get(pk=ldap_cn)
        
        self.assertEqual(ldap_user.display_name, '%s %s' % (first_name, last_name))
        
        member.delete();
        ldap_user.delete();


    def test_when_creating_member_ldap_cn_is_well_defined(self):
        """
        Lors de la création d'un membre, le champ "ldap_cn", s'il n'est pas 
        définit doit être généré avec les contraintes suivantes :
        premières lettres du prénom + nom le tout en minuscule, 
        sans caractères accentués et sans espaces.
        """
        random = os.urandom(4).encode('hex')
        first_name = u'Gérard-Étienne'
        last_name = u'Majax de la Boétie-Blop' + random
               
        control = 'gemajaxdelaboetieblop' + random
        
        member = Member(first_name = first_name, last_name = last_name)
        member.save()

        self.assertEqual(member.ldap_cn, control)
        
        member.delete();
        LdapUser.objects.get(pk=member.ldap_cn).delete();


class MemberAdminTests(TestCase):
    def setUp(self):
        #~ Client web
        self.client = Client()
        #~ Créé un superuser
        self.admin_user_password = '1234'
        self.admin_user = User.objects.create_superuser('test_admin_user', 'i@mail.com', self.admin_user_password)
        #~ Connection
        self.assertEqual(self.client.login(username = self.admin_user.username, password = self.admin_user_password),True)
        
    def test_cant_change_ldap_cn_when_editing(self):
        """
        Vérifie que dans l'admin Django, le champ ldap_cn n'est pad modifiable
        sur une fiche existante
        """
        #~ Créé un membre
        first_name = u'Gérard'
        last_name = u'Majax'
        ldap_cn = MemberTestsUtils.get_random_ldap_cn()
        member = Member(first_name = first_name, last_name = last_name, ldap_cn = ldap_cn)
        member.save()
        
        edit_page = self.client.get('/admin/members/member/%i/' % member.id)
        self.assertNotContains(edit_page,
            '''<input id="id_ldap_cn" />''',
            html=True)
        
        LdapUser.objects.get(pk=ldap_cn).delete();

class MemberTestsUtils(object):
    @staticmethod
    def get_random_ldap_cn():
        """
        Renvoi une clé aléatoire pour un utilisateur LDAP
        """
        return 'coin_test_' + os.urandom(8).encode('hex');
