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

from App.config import _config
from imio.helpers.security import check_zope_admin
from imio.helpers.security import fplog
from imio.helpers.security import generate_password
from imio.helpers.security import get_environment
from imio.helpers.security import get_user_from_criteria
from imio.helpers.security import get_zope_root
from imio.helpers.security import is_develop_environment
from imio.helpers.security import set_site_from_package_config
from imio.helpers.security import setup_logger
from imio.helpers.testing import IntegrationTestCase
from OFS.Application import Application
from plone import api
from plone.app.testing import login
from Products.CMFCore.permissions import ManagePortal
from Products.CMFCore.utils import _checkPermission
from Products.CMFPlone.Portal import PloneSite

import os
import re


class TestSecurityModule(IntegrationTestCase):
    """
    Test all helper methods of security module.
    """

    def setUp(self):
        if 'IS_DEV_ENV' in os.environ.keys():
            del os.environ['IS_DEV_ENV']
        if 'ENV' in os.environ.keys():
            del os.environ['ENV']
        self.portal = self.layer['portal']

    def test_fplog(self):
        fplog('test_action', 'test_extras')

    def test_is_develop_environment(self):
        os.environ['IS_DEV_ENV'] = 'false'
        self.assertFalse(is_develop_environment())
        os.environ['IS_DEV_ENV'] = 'true'
        self.assertTrue(is_develop_environment())

    def test_get_environment(self):
        os.environ['ENV'] = 'staging'
        self.assertFalse(is_develop_environment())
        self.assertEqual(get_environment(), 'staging')
        os.environ['ENV'] = 'dev'
        self.assertEqual(get_environment(), 'dev')
        self.assertTrue(is_develop_environment())

    def test_generate_password(self):
        pwd = generate_password(length=10, digits=1, upper=1, lower=1, special=1, readable=False)
        self.assertEqual(len(pwd), 10)
        self.assertIsNotNone(re.search(r'\d', pwd))
        self.assertIsNotNone(re.search(r'[A-Z]', pwd))
        self.assertIsNotNone(re.search(r'[a-z]', pwd))
        self.assertIsNotNone(re.search(r'[!#$%&*+<=>?@-]', pwd))

    def test_get_user_from_criteria(self):
        api.user.create('elementary@mail.be', 'ssmith', '12345', properties={'fullname': 'Stéphan Smith'})
        api.user.create('teacher@school.be', 'teacher', '12345', properties={'fullname': 'Paul Smith'})
        self.assertEqual(len(get_user_from_criteria(self.portal, email='unknown')), 0)
        self.assertEqual(len(get_user_from_criteria(self.portal, fullname='unknown')), 0)
        self.assertEqual(len(get_user_from_criteria(self.portal, userid='unknown')), 0)
        self.assertEqual(len(get_user_from_criteria(self.portal, email='mentary')), 1)
        self.assertEqual(len(get_user_from_criteria(self.portal, fullname='Stéph')), 1)
        self.assertEqual(len(get_user_from_criteria(self.portal, email='.be')), 2)
        self.assertEqual(len(get_user_from_criteria(self.portal, email='')), 3)
        self.assertEqual(len(get_user_from_criteria(self.portal, fullname='Smith')), 2)
        self.assertEqual(len(get_user_from_criteria(self.portal, fullname='')), 3)
        self.assertEqual(len(get_user_from_criteria(self.portal, userid='')), 3)
        self.assertEqual(len(get_user_from_criteria(self.portal, userid='teach')), 1)

    def test_setup_logger(self):
        # just call it to check that it is not broken
        self.assertIsNone(setup_logger())

    def test_get_zope_root(self):
        app = get_zope_root()
        self.assertIsInstance(app, Application)

    def test_set_site_from_package_config(self):
        # no config
        self.assertIsNone(set_site_from_package_config('imio.helpers'))
        # we add config
        _config.product_config = {'imio.helpers': {'plone-path': 'plone'}}
        site = set_site_from_package_config('imio.helpers')
        self.assertIsInstance(site, PloneSite)

    def test_check_zope_admin(self):
        # create and login as siteadmin
        self.portal.portal_membership.addMember('siteadmin', 'siteadmin', ['Manager'], [])
        login(self.portal, 'siteadmin')
        self.assertTrue(_checkPermission(ManagePortal, self.portal))
        self.assertFalse(check_zope_admin())
        # login as Zope admin
        login(self.portal.aq_parent, 'admin')
        self.assertTrue(_checkPermission(ManagePortal, self.portal))
        self.assertTrue(check_zope_admin())
