# -*- encoding: utf-8 -*-
#   Copyright 2008-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.
#
#   Authors: 
#       - Andrea Tomasini <andrea.tomasini__at__agile42.com>

from agilo.api import controller, validator
from agilo.scrum.backlog.model import BacklogModelManager
from trac.util.translation import _

__all__ = ['BacklogController']


class BacklogController(controller.Controller):
    """Controller to perform operations on the Backlog Object"""
    
    def __init__(self):
        """Create a reference to the Model Manager"""
        self.manager = BacklogModelManager(self.env)
    
    
    class GetBacklogCommand(controller.ICommand):
        """Retrieves a Backlog given its name. The reload parameter,
        set to True force a reload of the backlog tickets."""
        # AT: Due to the implemented Object Identity though, there should 
        # not be any need of reloading a backlog, the parameters is 
        # offered to be used in those cases when a server with 
        # multiple processors uses a Python VM which is not supporting 
        # that configuration de facto duplicating the items in every 
        # VM space.
        parameters = {'name': validator.MandatoryStringValidator,
                      'scope': validator.StringValidator,
                      'reload': validator.BoolValidator,
                      'filter_by': validator.StringValidator}
        
        def _execute(self, backlog_controller, date_converter, as_key):
            return backlog_controller.manager.get(name=self.name,
                                                  scope=self.scope,
                                                  reload=self.reload,
                                                  filter_by=self.filter_by)
    
    
    class ListBacklogsCommand(controller.ICommand):
        """Returns the list of Backlogs available"""
        parameters = {}
        
        def _execute(self, backlog_controller, date_converter, as_key):
            backlog_list = backlog_controller.manager.select()
            return [controller.ValueObject(b.as_dict()) \
                    for b in backlog_list]
    
    
    class CreateBacklogCommand(controller.ICommand):
        """Creates a Backlog object with the given properties"""
        parameters = {'name': validator.MandatoryStringValidator,
                      'ticket_types': validator.IterableValidator, 
                      'sorting_keys': validator.IterableValidator, 
                      'scope': validator.StringValidator,
                      'b_type': validator.IntValidator, 
                      'load': validator.BoolValidator, 
                      'description': validator.StringValidator, 
                      'b_strict': validator.BoolValidator, 
                      'filter_by': validator.StringValidator}
        
        def _execute(self, backlog_controller, date_converter, as_key):
            """Create the backlog and returns it after saving it"""
            return backlog_controller.manager.create(name=self.name,
                                                     ticket_types=self.ticket_types,
                                                     sorting_keys=self.sorting_keys,
                                                     scope=self.scope,
                                                     b_type=self.b_type,
                                                     load=self.load,
                                                     description=self.description,
                                                     b_strict=self.b_strict,
                                                     filter_by=self.filter_by)
        
        
    class MoveBacklogItemCommand(GetBacklogCommand):
        """Allows to move a Backlog Item from a position to another of
        a backlog identified by name and scope."""
        
        parameters = {'name': validator.MandatoryStringValidator,
                      'scope': validator.StringValidator,
                      'ticket': validator.MandatoryTicketValidator,
                      'to_pos': validator.MandatoryIntValidator,
                      'from_pos': validator.IntValidator}
        
        def _execute(self, backlog_controller, date_converter, as_key):
            """Execute the item move"""
            # We have to load the tickets if it is not a global backlog
            if self.scope:
                self.reload = True
            s_cmd = super(BacklogController.MoveBacklogItemCommand, self)
            backlog = s_cmd._execute(backlog_controller, date_converter, as_key)
            if backlog.move(self.ticket, self.to_pos, self.from_pos):
                return backlog_controller.manager.save(backlog)
    
    
    class SaveBacklogCommand(GetBacklogCommand):
        """Saves the Backlog with the given parameters"""
        
        parameters = {'name': validator.MandatoryStringValidator,
                      'ticket_types': validator.IterableValidator, 
                      'sorting_keys': validator.IterableValidator, 
                      'scope': validator.StringValidator,
                      'b_type': validator.IntValidator, 
                      'description': validator.StringValidator, 
                      'b_strict': validator.BoolValidator, 
                      'filter_by': validator.StringValidator,
                      'tickets': validator.IterableValidator,
                      'author': validator.StringValidator,
                      'comment': validator.StringValidator}
        
        def _execute(self, backlog_controller, date_converter, as_key):
            # Retrives and save the backlog
            s_cmd = super(BacklogController.SaveBacklogCommand, self)
            backlog = s_cmd._execute(backlog_controller, date_converter, as_key)
            
            for param in self.parameters:
                if param not in ('author', 'comment'):
                    value = getattr(self, param, None)
                    if value is not None:
                        if param == 'tickets':
                            param = '_' + param
                        setattr(backlog, param, value)
            # Now use the manager to save the backlog
            return backlog_controller.manager.save(backlog, author=self.author,
                                                   comment=self.comment)
    