# Elisa - Home multimedia server
# Copyright (C) 2006-2008 Fluendo Embedded S.L. (www.fluendo.com).
# All rights reserved.
#
# This file is available under one of two license agreements.
#
# This file is licensed under the GPL version 3.
# See "LICENSE.GPL" in the root of this distribution including a special
# exception to use Elisa with Fluendo's plugins.
#
# The GPL part of Elisa is also available under a commercial licensing
# agreement from Fluendo.
# See "LICENSE.Elisa" in the root directory of this distribution package
# for details on that license.

from elisa.extern.translation import Translator

from elisa.core import log, common
#FIXME : BAD HACK to disable the reactor installation in test mode 
common.from_test = True

from elisa.core import application
from elisa.core import config, plugin_registry
from elisa.core import interface_controller
from elisa.core import media_manager
from elisa.core import metadata_manager
from elisa.core import input_manager
from elisa.core import plugin
from elisa.core.bus import bus
from elisa.base_components import view, context, activity, model, controller,\
     theme
from elisa.extern.log import log as extern_log

from twisted.trial import unittest
import os, sys, inspect



DEFAULT_CONFIG = """\
[general]
version = '%(version)s'
install_date = '%(install_date)s'
media_providers = []
metadata_providers = []
service_providers = []
player_engines = []
backends = ['backend1']
frontends = ['frontend1']

[media_db:media_scanner]
enabled = '1'
fivemin_location_updates = []
hourly_location_updates = []
daily_location_updates = []
weekly_location_updates = []
unmonitored_locations = []

[media_db:db]
db_backend = 'sqlite'
database = 'elisa.db'

[backend1]
activity = 'test:elisa_activity'
mvc_mappings = 'test_mvc_mappings.conf'
input_providers = []

[frontend1]
backend = 'backend1'
theme = 'test:test_theme'
input_providers = []

[xmlmenu:locations_builder]
locations = []
auto_locations = 1

[lirc:lirc_input]
# filename of the LIRC config map to use
lirc_rc = 'streamzap.lirc'
delay = '4'
repeat = '1'

[coherence:coherence_service]
logmode = 'none'
controlpoint = 'yes'

[[plugins]]

[base:service_activity]
# a list of activites, which should beappear in the service_menu
service_activities = ['service:about_activity']

[player]
audiosink = 'autoaudiosink'

[theme_switcher:theme_switcher_activity]
# a list of themes 'plugin:component' like 'classic:theme'
themes = ['poblenou:tango_theme', 'poblenou:poblenou_theme', 'poblenou:chris_theme']
"""


MAPPINGS="""\
[test:elisa_model]
supported_controllers = ['test:elisa_controller',]
controller = 'test:elisa_controller'
supported_views = ['test:elisa_view']
view = 'test:elisa_view'
"""

class TestTheme(theme.Theme):
    name = 'test_theme'

class TestModel(model.Model):
    name = 'elisa_model'
    path = 'test:elisa_model'
    
class TestController(controller.Controller):
    name = 'elisa_controller'
    supported_models = ('test:elisa_model',)

class TestActivity(activity.Activity):
    name = 'elisa_activity'

    def get_model(self):
        return TestModel()

class TestView(view.View):
    name = 'elisa_view'
    context_path = 'test:elisa_context'
    supported_controllers = ('test:elisa_controller',)
    
class TestContext(context.Context):
    name = 'elisa_context'
    
class TestPlugin(plugin.Plugin):
    name = 'test'
    components = {'elisa_model': {'path': TestModel},
                  'elisa_controller': {'path': TestController},
                  'elisa_view': {'path': TestView},
                  'elisa_context': {'path': TestContext},
                  'elisa_activity': {'path': TestActivity},
                  'test_theme': {'path': TestTheme},
                  }
    
class BoilerPlateApp:

    def __init__(self, config_file, default_config=None, load_all_plugins=False):
        #self.config = config.Config(config_file)
        if not default_config:
            default_config = DEFAULT_CONFIG
        self.errors = []
        
        default_config = default_config % {'version': 'test',
                                           'install_date': 'none'}
        self.config = config.Config('empty.conf', default_config)
        common.set_application(self)

        self.translator = Translator()
        manager = plugin_registry.PluginRegistry(self.config)
        if load_all_plugins:
            manager.load_plugins()
        manager.register_plugin(TestPlugin)
        
        self.plugin_registry = manager
        self.bus = bus.Bus()
        self.media_manager = media_manager.MediaManager(None)
        self.metadata_manager = metadata_manager.MetadataManager()
        self.input_manager = input_manager.InputManager()
        self.interface_controller = interface_controller.InterfaceController()
        self.interface_controller.initialize()
        
    def log_traceback(self):
        info = sys.exc_info()
        self.errors.append(info)

    def log_failure(self, failure):
        self.errors.append(failure)

class ElisaTestCase(unittest.TestCase, extern_log.Loggable):
    default_config = DEFAULT_CONFIG
    load_all_plugins = False
    tests_dir = os.path.dirname(__file__)
    
    def __init__(self, methodName='runTest'):
        self._booted = False
        
        test_file_path = inspect.getsourcefile(self.__class__)
        if test_file_path is not None:
            fname = os.path.basename(test_file_path)

            fname, _ = os.path.splitext(fname)
            self.logCategory = fname
            self.directory = os.path.dirname(test_file_path)
        
        #extern_log.init('ELISA_TESTS')
        unittest.TestCase.__init__(self, methodName=methodName)

    debug = extern_log.Loggable.debug
    info = extern_log.Loggable.info

    def _boot(self):
        if self._booted == False:
            common.boot()

            if 'ELISA_DEBUG' not in os.environ:
                log.setDebug('*:0')

            f = open('test_mvc_mappings.conf','w')
            f.write(MAPPINGS)
            f.close()

            app = BoilerPlateApp('empty.conf', self.default_config,
                                 self.load_all_plugins)
            self.debug("Set common.application to %r", app)
            
            self._booted = True
    
    def setUp(self):
        self._boot()
        
    def check_called(self, callback):
        self.failUnless(hasattr(callback, 'called'))
        self.assertEquals(callback.called, True)
