# Licensed under the MIT license
# http://opensource.org/licenses/mit-license.php

# Copyright (C) 2006 Fluendo, S.A. (www.fluendo.com).
# Copyright 2006, Frank Scholz <coherence@beebits.net>

import time
from sets import Set

from coherence.upnp.core import utils
try:
    #FIXME:
    # there is some circular import, service imports variable, variable imports service
    # how is this done properly?
    #
    from coherence.upnp.core import service
except ImportError:
    import service
    
from coherence import log

class StateVariable(log.Loggable):
    logCategory = 'variable'
    
    def __init__(self, upnp_service, name, implementation, instance, send_events,
                 data_type, values):
        self.service = upnp_service
        self.instance = instance
        self.name = name
        self.implementation = implementation
        self.data_type = data_type
        self.allowed_values = values
        self.has_vendor_values = False
        self.dependant_variable = None
        self.default_value = ''
        self.old_value = ''
        self.value = ''
        self.last_time_touched = time.time()
        self.allowed_value_range = None
        self.never_evented = False
        if send_events in [True,1,'1','true','True','yes','Yes']:
            self.send_events = True
        else:
            self.send_events = False
        self._callbacks = []
        if isinstance( self.service, service.ServiceServer):
            self.moderated = self.service.is_variable_moderated(name)
            self.updated = False

    def set_default_value(self, value):
        self.update(value)
        self.default_value = self.value
        
    def set_allowed_values(self, values):
        if not isinstance(values,list):
            values = [values]
        self.allowed_values = values
        
    def set_allowed_value_range(self, **kwargs):
        self.allowed_value_range = kwargs
        
    def get_allowed_values(self):
        return self.allowed_values
    
    def set_never_evented(self, value):
        if value in [True,1,'1','true','True','yes','Yes']:
            self.never_evented = True
            
    def update(self, value):
        self.info("variable check for update", self.name, value, self.service)
        if not isinstance( self.service, service.Service):
            if self.name == 'ContainerUpdateIDs':
                old_value = self.value
                if self.updated == True:
                    if isinstance( value, tuple):
                        v = old_value.split(',')
                        i = 0
                        while i < len(v):
                            if v[i] == str(value[0]):
                                del v[i:i+2]
                                old_value = ','.join(v)
                                break;
                            i += 2
                        if len(old_value):
                            new_value = old_value + ',' + str(value[0]) + ',' + str(value[1])
                        else:
                            new_value = str(value[0]) + ',' + str(value[1])
                    else:
                        if len(old_value):
                            new_value = str(old_value) + ',' + str(value)
                        else:
                            new_value = str(value)
                else:
                    if isinstance( value, tuple):
                        new_value = str(value[0]) + ',' + str(value[1])
                    else:
                        new_value = value
            else:
                if self.data_type == 'string':
                    if isinstance(value,basestring):
                        value = value.split(',')
                    if(isinstance(value,tuple) or
                       isinstance(value,Set)):
                        value = list(value)
                    if not isinstance(value,list):
                        value = [value]
                    new_value = []
                    for v in value:
                        if type(v) == unicode:
                            v = v.encode('utf-8')
                        else:
                            v = str(v)
                        if len(self.allowed_values):
                            if self.has_vendor_values == True:
                                new_value.append(v)
                            elif v.upper() in [x.upper() for x in self.allowed_values]:
                                new_value.append(v)
                            else:
                                self.warning("Variable %s update, value %s doesn't fit" % (self.name, v))
                                new_value = 'Coherence_Value_Error'
                        else:
                            new_value.append(v)
                    new_value = ','.join(new_value)
                elif self.data_type == 'boolean':
                    if value in [True,1,'1','true','True','yes','Yes']:
                        new_value = '1'
                    else:
                        new_value = '0'
                else:
                    new_value = int(value)
        else:
            if self.data_type == 'string':
                if type(value) == unicode:
                    value = value.encode('utf-8')
                else:
                    value = str(value)
                if len(self.allowed_values):
                    if self.has_vendor_values == True:
                        new_value = value
                    elif value.upper() in [v.upper() for v in self.allowed_values]:
                        new_value = value
                    else:
                        self.warning("Variable %s NOT updated, value %s doesn't fit" % (self.name, value))
                        new_value = 'Coherence_Value_Error'
                else:
                    new_value = value
            elif self.data_type == 'boolean':
                if value in [1,'true','True','yes','Yes']:
                    new_value = '1'
                else:
                    new_value = '0'
            else:
                new_value = int(value)

        if new_value == 'Coherence_Value_Error':
            return
        if new_value == self.value:
            self.info("variable NOT updated, no value change", self.name, self.value)
            return
        self.old_value = self.value
        self.value = new_value
        self.last_time_touched = time.time()

        if isinstance( self.service, service.Service):
            self.notify()
        else:
            self.updated = True
            if self.service.last_change != None:
                self.service.last_change.updated = True
        self.info("variable updated", self.name, self.value)

    def subscribe(self, callback):
        self._callbacks.append(callback)
        
    def notify(self):
        for callback in self._callbacks:
            callback( self)
            
    def __repr__(self):
        return "Variable: %s, %s, %d, %s, %s, %s, %s, %s, %s" % \
                        (self.name,
                         str(self.service),
                         self.instance,
                         self.implementation,
                         self.data_type,
                         str(self.allowed_values),
                         str(self.default_value),
                         str(self.value),
                         str(self.send_events))


@@ -485,20 +485,16 @@
 service%0A
-    
 %0Afrom co
@@ -577,20 +577,16 @@
 riable'%0A
-    
 %0A    def
@@ -1644,25 +1644,17 @@
 f.value%0A
-        
 %0A
+
     def 
@@ -1794,25 +1794,17 @@
  values%0A
-        
 %0A
+
     def 
@@ -1886,25 +1886,17 @@
  kwargs%0A
-        
 %0A
+
     def 
@@ -1956,21 +1956,17 @@
 _values%0A
-    
 %0A
+
     def 
@@ -2095,28 +2095,16 @@
  = True%0A
-            
 %0A    def
@@ -6728,24 +6728,16 @@
 llback)%0A
-        
 %0A    def
@@ -6818,30 +6818,43 @@
 ck( self
-)%0A            
+, self.service.device.usn)%0A
 %0A    def
@@ -7334,9 +7334,8 @@
 vents))%0A
-%0A

add the device usn as a parameter to the StateVariable updated notification