#-------------------------------------------------------------------------------
#  
#  Defines an adapter from an enthought.contexts.api.IContext
#  to an ITemplateDataContext.
#  
#  Written by: David C. Morrill
#  Modified by: Robert Kern
#  
#  Date: 11/16/2007
#  
#  (c) Copyright 2007 by Enthought, Inc.
#  
#-------------------------------------------------------------------------------

""" Defines an adapter from an enthought.contexts.api.IContext to an
    ITemplateDataContext.
"""

#-------------------------------------------------------------------------------
#  Imports:
#-------------------------------------------------------------------------------

from enthought.traits.api \
    import Adapter, Str, List, adapts

from enthought.traits.protocols.api \
    import AdaptationError, adapt
    
from enthought.contexts.api \
    import IContext
    
from enthought.template.itemplate_data_context \
    import ITemplateDataContext, ITemplateDataContextError
    
from helper \
    import path_for
    
#-------------------------------------------------------------------------------
#  'IContextAdapter' class:
#-------------------------------------------------------------------------------

class IContextAdapter ( Adapter ):
    """ Defines an adapter from an enthought.contexts.api.IContext
        to an ITemplateDataContext.
    """
    
    adapts( IContext, ITemplateDataContext )
    
    #-- ITemplateDataContext Interface Implementation --------------------------
    
    # The path to this data context (does not include the 'data_context_name'):
    data_context_path = Str
    
    # The name of the data context:
    data_context_name = Str
    
    # A list of the names of the data values in this context:
    data_context_values = List( Str )
    
    # The list of the names of the sub-contexts of this context:
    data_contexts = List( Str )
    
    def get_data_context_value ( self, name ):
        """ Returns the data value with the specified *name*. Raises a
            **ITemplateDataContextError** if *name* is not defined as a data
            value in the context.
            
            Parameters
            ----------
            name : A string specifying the name of the context data value to
                be returned.
                
            Returns
            -------
            The data value associated with *name* in the context. The type of
            the data is application dependent.
            
            Raises **ITemplateDataContextError** if *name* is not associated 
            with a data value in the context.
        """
        try:
            if name in self.data_context_values:
                return self.adaptee[ name ]
                
            raise ITemplateDataContextError( 
                      "No value named '%s' found." % name )
        except Exception, excp:
            raise ITemplateDataContextError( str( excp ) ) 
        
    def get_data_context ( self, name ):
        """ Returns the **ITemplateDataContext** value associated with the
            specified *name*. Raises **ITemplateDataContextError** if *name* is
            not defined as a data context in the context.
            
            Parameters
            ----------
            name : A string specifying the name of the data context to be 
                returned.
                
            Returns
            -------
            The **ITemplateDataContext** associated with *name* in the context.
            
            Raises **ITemplateDataContextError** if *name* is not associated 
            with a data context in the context.
        """
        try:
            if name in self.data_contexts:
                bdca = IContextAdapter( self.adaptee[ name ] )
                bdca.data_context_path = path_for( self.data_context_path,
                                                   self.data_context_name )
                return bdca                                                   
                
            raise ITemplateDataContextError( 
                      "No context named '%s' found." % name )
        except Exception, excp:
            raise ITemplateDataContextError( str( excp ) ) 
    
    #-- Traits Event Handlers --------------------------------------------------
    
    def _adaptee_changed ( self, context ):
        """ Handles being bound to a IContext object.
        """
        self.data_context_name = context.name
        values   = []
        contexts = []
        for name in context.keys():
            value = context[ name ]
            try:
                adapt( value, IContext )
            except AdaptationError:
                # Is not a subcontext.
                values.append( name )
            else:
                # Is a subcontext.
                contexts.append( name )
                
        self.data_context_values = values
        self.data_contexts       = contexts
        
