# -*- encoding: utf-8 -*-
#   Copyright 2008 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 pkg_resources import resource_filename
from random import randint

from genshi.template import TemplateLoader, MarkupTemplate
from trac.web.chrome import add_script, Chrome
from trac.util.translation import _


class Widget(object):
    """Widgets encapsulate HTML+Javascript+CSS for commonly used building 
    blocks like charts."""
    
    def _define_chart_resources(self, env, template_filename, kwargs, scripts=None):
        """Helper method for inherited class that removes template_filename and
        scripts from kwargs if present."""
        # Remove template_file and scripts so that we don't get a duplicate
        # keywork exception
        kwargs.pop('template_filename', None)
        kwargs.pop('scripts', None)
    
    def __init__(self, env, template_filename, scripts=None, **kwargs):
        # env is pretty much a requirement for most widgets so for convenience,
        # I'm just saving it here
        self.env = env
        self.template_filename = template_filename
        
        # Every widget instance needs to have a unique id so that you can have 
        # multiple graphs from the same widget on one page.
        if 'unique_id' in kwargs:
            del kwargs['unique_id']
        self.data = kwargs.copy()
        self.data['unique_id'] = randint(0,1000000)
        
        self.scripts = scripts or list()
        self.rendering_prepared = False
    
    def copy(self):
        """Return a shallow copy of this widget (env will not be copied!)"""
        new_widget = self.__class__(self.env, template_filename=self.template_filename, 
                                    scripts=self.scripts, **self.data)
        return new_widget
    
    def update_data(self, *args, **kwargs):
        """Be careful when adding additional data after the widget was 
        generated - many widgets (actually all so far ;-) have a custom 
        initialization method that adds all necessary information given a 
        special key. This method is on a lower level so you may need to set 
        quite a lot of variables if you do it on your own."""
        if len(args) > 0:
            for item in args:
                assert isinstance(item, dict)
                self.data.update(item)
        self.data.update(kwargs)
    
    def _merge_data(self, data):
        real_data = self.data.copy()
        real_data.update(data)
        return real_data
    
    def prepare_rendering(self, req):
        """This method must be called before Trac started rendering the template
        so that we can add items to the global header."""
        for script_filename in self.scripts:
            add_script(req, script_filename)
        self.data['req'] = req
        self.rendering_prepared = True
    
    def _get_all_widget_template_directories(self):
        # AT: must be a real path not . or .. in eggs will not work
        trac_template_dirs = Chrome(self.env).get_all_templates_dirs()
        template_directories = [resource_filename('agilo', '')] + trac_template_dirs
        return template_directories
    
    def display(self, **data):
        """Return the HTML code for the given widget."""
        if len(self.scripts)> 0:
            assert self.rendering_prepared, 'You have to prepare_rendering before you can display things.'
        templateloader = TemplateLoader(self._get_all_widget_template_directories(),
                                      auto_reload=True, variable_lookup='lenient')
        template = templateloader.load(self.template_filename, cls=MarkupTemplate)
        template_data = self._merge_data(data)
        return template.generate(**template_data)


