# -*- encoding: utf-8 -*-
#   Copyright 2009 Agile42 GmbH, Berlin (Germany)
#
#   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.
#   
#   Author: 
#       - Felix Schwarz <felix.schwarz__at__agile42.com>

from trac.util.datefmt import to_datetime
from trac.tests.functional import tc
from twill.errors import TwillAssertionError

from agilo.utils import Key, Type
from agilo.utils.config import AgiloConfig
from agilo.test import Usernames
from agilo.test.functional import AgiloTestCase


class FilteredBacklogTest(AgiloTestCase):
    """Base class with functionality to test filtering backlogs by component."""
    
    def _set_filter_for_backlog(self, attribute_name, enable=True):
        env = self._testenv.get_trac_environment()
        ac = AgiloConfig(env)
        config = ac.get_section(AgiloConfig.AGILO_GENERAL)
        option = 'backlog_filter_attribute'
        if enable:
            config.set_option(option, attribute_name)
        else:
            config.remove_option(option)
        config.save()
        if enable:
            assert ac.backlog_filter_attribute == attribute_name
    
    def assert_visibility_in_backlog(self, *visibility):
        """Given a list of booleans it asserts that the associated tasks (index
        in self.tasks) are visible/hidden in the currently shown backlog."""
        for task, should_be_visible in zip(self.tasks, visibility):
            is_visible = self._tester.is_ticket_visible_in_backlog
            error = '%s != %s for #%s' % (should_be_visible, is_visible(task), task)
            self.assertEqual(should_be_visible, is_visible(task), error)


class TestBacklogCanBeFilteredByComponent(FilteredBacklogTest):
    """Check that the backlog can be really filtered by component."""
    
    def _create_sprint_with_tasks(self, sprint_name):
        milestone_name = sprint_name + 'Milestone'
        self._tester.create_milestone(milestone_name)
        self._tester.create_sprint_for_milestone(milestone_name, sprint_name, 
                                                 to_datetime(None), duration=10)
        # component1 + component2 are components which are created by trac for
        # a new environment - I assume that no other functional test removed 
        # them...
        create_task = self._tester.create_new_agilo_task
        self.tasks = [
            create_task('Task1', sprint=sprint_name, component='component1'),
            create_task('Task2', sprint=sprint_name, component='component2'),
            create_task('Task3', sprint=sprint_name),
        ]
    
    def _check_that_no_filtering_is_applied_by_default(self, sprint_name):
        self._tester.navigate_to_sprint_backlog(sprint_name)
        self.assert_visibility_in_backlog(True, True, True)
    
    def _check_that_backlog_can_be_filtered(self):
        tc.formvalue('filter_attribute_chooser', 'filter_by', '+component1')
        tc.submit()
        self.assert_visibility_in_backlog(True, False, True)
    
    def _check_that_chosen_filter_option_is_preselected(self):
        self._tester.select_form_for_twill('filter_attribute_chooser', 
                                           'choose_filter_submit')
        tc.submit()
        self.assert_visibility_in_backlog(True, False, True)
    
    def _check_that_filtering_can_be_reset(self):
        tc.formvalue('filter_attribute_chooser', 'filter_by', '+')
        tc.submit()
        self.assert_visibility_in_backlog(True, True, True)
    
    def runTest(self):
        self._tester.login_as(Usernames.admin)
        self._tester.show_field_for_type(Key.COMPONENT, Type.TASK)
        sprint_name = 'BacklogCanBeFilteredByComponentSprint'
        self._create_sprint_with_tasks(sprint_name)
        self._set_filter_for_backlog(Key.COMPONENT)
        
        try:
            self._check_that_no_filtering_is_applied_by_default(sprint_name)
            self._check_that_backlog_can_be_filtered()
            self._check_that_chosen_filter_option_is_preselected()
            self._check_that_filtering_can_be_reset()
        finally:
            self._set_filter_for_backlog(Key.COMPONENT, False)
            self._tester.hide_field_for_type(Key.COMPONENT, Type.TASK)


class TestNoAdditionalFilteringForMilestoneAndProductBacklogs(FilteredBacklogTest):
    def runTest(self):
        self._tester.login_as(Usernames.admin)
        self._tester.show_field_for_type(Key.COMPONENT, Type.TASK)
        self._set_filter_for_backlog(Key.COMPONENT)
        
        self._tester.navigate_to_product_backlog()
        self.assertRaises(TwillAssertionError, tc.formvalue, 
                          'filter_attribute_chooser', 'filter_by', 'foo')



if __name__ == '__main__':
    from agilo.test.testfinder import run_all_tests
    run_all_tests(__file__)

