# -*- coding: utf-8 -*-
#   Copyright 2009 Agile42 GmbH
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
# 
# Authors:
#     - Felix Schwarz <felix.schwarz__at__agile42.com>

import os

from pkg_resources import resource_filename
from trac.tests.functional import tc

from agilo.utils import Role

from agilo.test.functional.agilo_tester import AgiloTester, Usernames
from agilo.test.functional.trac_environment import TracFunctionalTestEnvironment

__all__ = ['AgiloFunctionalTestEnvironment']




class AgiloFunctionalTestEnvironment(TracFunctionalTestEnvironment):
    
    # -------------------------------------------------------------------------
    # Overwritten methods
    def __init__(self):
        super(AgiloFunctionalTestEnvironment, self).__init__()
        self._add_agilo_to_pythonpath()
    
    def build_tester(self):
        trac_env = self.get_trac_environment()
        tester = AgiloTester(self.url, self.repo_url, trac_env)
        return tester
    
    def create(self):
        # We need to disable the validation before any request is made
        self._disable_xhtml_validation()
        if not super(AgiloFunctionalTestEnvironment, self).create():
            return False
        
        if 'DISABLE_AGILO_UI' in os.environ:
            self.disable_agilo_ui()
        self._print_system_information()
        return True
    
    def get_enabled_components(self):
        components = super(AgiloFunctionalTestEnvironment, self).get_enabled_components()
        components += ['agilo.*', 'webadmin.*', 'acct_mgr.*']
        return components
    
    def get_disabled_components(self):
        components = super(AgiloFunctionalTestEnvironment, self).get_disabled_components()
        components += ['trac.ticket.web_ui.ticketmodule',
                       'trac.ticket.roadmap.roadmapmodule',
                       'trac.ticket.api.ticketsystem',
                       # If registration is enabled, this might affect our tests
                       # because users will be limited to anonymous.
                       'acct_mgr.web_ui.EmailVerificationModule',
                      ]
        return components
    
    def get_config_options(self):
        options = super(AgiloFunctionalTestEnvironment, self).get_config_options()
        options += [('trac', 'permission_policies', 'AgiloPolicy, DefaultPermissionPolicy, LegacyAttachmentPolicy'),
                    ('account-manager', 'password_file', self.htpasswd),
                    ('account-manager', 'generated_password_length', '8'),
                    ('account-manager', 'hash_method', 'HtDigestHashMethod'),
                    ('account-manager', 'password_store', 'HtPasswdStore'),
                    # Disable logging that will only slow down tests
                    ('logging', 'log_type', 'None'),
                    ('logging', 'log_level', 'INFO'),
                   ]
        return options
    
    def get_users_and_permissions(self):
        userinfo = super(AgiloFunctionalTestEnvironment, self).get_users_and_permissions()
        userinfo += [(Usernames.scrum_master, [Role.SCRUM_MASTER]),
                     (Usernames.product_owner, [Role.PRODUCT_OWNER]),
                     (Usernames.team_member, [Role.TEAM_MEMBER]),
                     (Usernames.second_team_member, [Role.TEAM_MEMBER]),]
        return userinfo
    
    def get_key(cls):
        return 'agilo'
    get_key = classmethod(get_key)
    # -------------------------------------------------------------------------
    # New methods for Agilo
    
    def _add_agilo_to_pythonpath(self):
        # Export in the environment the PYTHONPATH including the current
        # Agilo root dir, this is needed because trac will be launched as
        # an external process via Popen, and the sys.path with not be propagated
        agilo_root = os.path.abspath(resource_filename('agilo', '..'))
        # msg = "Exporting PYTHONPATH with current Agilo for Trac standalone:%s" % agilo_root
        # print msg
        new_pythonpath = os.getenv('PYTHONPATH', '') + os.pathsep + agilo_root
        os.environ['PYTHONPATH'] = new_pythonpath
    
    def _disable_xhtml_validation(self):
        # We need to disable trac's validation of the returned HTML pages 
        # because we generate invalid xhtml sometimes (e.g. custom attributes
        # in the search input field, ul elements without li).
        # In the old suite this worked implicitely because we reset the browser
        # in the beginning.
        b = tc.get_browser()
        # TODO: This is a bit brutal right now but actually there are no other
        # post load hooks used right now. Refine if necessary.
        b._post_load_hooks = []
    
    def _print_system_information(self):
        """Prints the system information for better debugging"""
        sys_info = ['============= System Information =============']
        for prop, value in self.get_trac_environment().systeminfo:
            sys_info.append("  %s: '%s'" % (prop.ljust(10), value))
        sys_info.append('==============================================')
        self.logfile.write(''.join(sys_info))
    
    def disable_agilo_ui(self):
        env = self.get_trac_environment()
        default_value = 'notset'
        inherit_path = env.config.get('inherit', 'templates_dir', default=default_value)
        if inherit_path != default_value:
            env.config.set('inherit', 'templates_dir', None)
            env.config.save()





# Register this module with the EnvironmentBuilder
from agilo.test.functional.api import EnvironmentBuilder
EnvironmentBuilder.register_environment(AgiloFunctionalTestEnvironment.get_key(),
                                        AgiloFunctionalTestEnvironment)

