import unittest
try:
    from Scenario2.interpolators import *
    from Scenario2.keyframes import KF, ValueGenerator, Interval
except:
    print "ERROR: failed to import scenario.interpolators"


    
import types
from math import *
import numpy

def sameIntSequences(list1, list2):
    for a,b in zip(list1,list2):
        if a!=b:
            return False
    return True

def sameFloatSequences(list1, list2):
    for a,b in zip(list1,list2):
        try:
            len(a)
            len(b)
            for c,d in zip(a, b):
                if "%.2f"%c !=  "%.2f"%c:
                   print  a , "!=", b
                   return False
        except:
            if "%.2f"%a !=  "%.2f"%b:
                print  "%.2f"%a , "%.2f"%b
                return False
    return True

def adding(x):
    return x+x
     
def withargs(x,y,height,width):
    z=x*y*height*width
    return z
    
def simple(x):
    return x

def sinfunc(mod,x):
    return round(sin(mod))
    
def cosfunc(x):
    return cos(x)


# BooleanInterpolator, CompositeInterpolator,  ReadDataInterpolator

class ValueGeneratorTest(unittest.TestCase):


    def test_IntScalarInterpolators(self):

        kf1 = KF(0, 0)
        kf2 = KF(20, 10)
        valGen = ValueGenerator()
        i1 = Interval(kf1, kf2, valGen)
        ip = IntScalarInterpolator(None, None)
        i1.setValGenGenerator(ip)
        
        val = i1.valGen.getValue(0.0, i1)
        self.assertEqual(val, i1.valGen.generator.firstVal)
        self.assertEqual(val, 0)
        
        val = i1.valGen.getValue(1.0, i1)
        self.assertEqual( val, i1.valGen.generator.lastVal)
        self.assertEqual(val, 10)
        
        self.assertEqual( i1.valGen.getValue(0.3, i1), 3)
        self.assertEqual( i1.valGen.getValue(0.34, i1), 3)
        self.assertEqual( i1.valGen.getValue(0.38, i1), 4)
        
        #test configure()
        i1.valGen.generator.configure(firstVal = 25, lastVal = 30)
        val = i1.valGen.getValue(0.0, i1)
        self.assertEqual(val, 25)
        val = i1.valGen.getValue(1.0, i1)
        self.assertEqual( val, 30)
        self.assertEqual(i1.valGen.generator.valueRange, 5)
        self.assertEqual( i1.valGen.getValue(0.5, i1), 28)
        

    def test_FloatScalarInterpolator(self):

        kf1 = KF(0, 0.)
        kf2 = KF(20, 10.)
        valGen = ValueGenerator()
        i1 = Interval(kf1, kf2, valGen)
        
        ip = FloatScalarInterpolator(None, None)
        bl = BehaviorList(None, None)
        bl.addBehavior(ip)
        i1.setValGenGenerator(bl)
        
        val = i1.valGen.getValue(0.0, i1)
        firstVal = i1.valGen.generator.firstVal 
        self.assertEqual(val, firstVal)
        self.assertEqual(0., firstVal)
        
        val = i1.valGen.getValue(1.0, i1)
        lastVal = i1.valGen.generator.lastVal
        self.assertEqual( val, lastVal)
        self.assertEqual( 10., lastVal)
        
        val = "%.2f" % i1.valGen.getValue(0.35, i1)
        self.assertEqual(val, "3.50")
        val = "%.2f" % i1.valGen.getValue(0.5, i1)
        self.assertEqual(val, "5.00")
        
        #testconfigure()
        i1.valGen.generator.configure(firstVal = 25.5, lastVal = 30.5)
        val = "%.2f" % i1.valGen.getValue(0.0, i1)
        self.assertEqual(val, "25.50")
        val = "%.2f" % i1.valGen.getValue(1.0, i1)
        self.assertEqual( val, "30.50")
        self.assertEqual("%.2f" % i1.valGen.generator.behaviors[0].valueRange, "5.00")
        val =  "%.2f" % i1.valGen.getValue(0.56, i1)
        self.assertEqual( val, "28.30")
        
        i1.valGen.generator.configure(active = False)
        self.assertEqual(ip.active, False)
    


    def test_IntVarScalarInterpolator(self):
        kf1 = KF(0, 1)
        kf2 = KF(20, [2,4,6])
        valGen = ValueGenerator()
        i1 = Interval(kf1, kf2, valGen)
        
        bl = BehaviorList(None, None)
        ip = IntVarScalarInterpolator (None, None)
        bl.addBehavior(ip)
        i1.setValGenGenerator(bl)

        val = i1.valGen.getValue(0.0, i1 )
        firstVal = i1.valGen.generator.firstVal 
        self.assertEqual(val, [firstVal,])
        self.assertEqual(firstVal, 1)
        
        val = i1.valGen.getValue(1.0, i1)
        lastVal = i1.valGen.generator.lastVal
        self.assertEqual( val, lastVal)
        self.assertEqual(lastVal, [2,4,6])
        
        val = i1.valGen.getValue(0.5, i1)
        self.assertEqual(val, [2, 3, 4])
        val = i1.valGen.getValue(0.6, i1)
        self.assertEqual(val,[2, 3, 4])
        val = i1.valGen.getValue(0.67, i1)
        self.assertEqual(val, [2, 3, 4])  
        # configure()
        i1.valGen.generator.configure(firstVal = [2,4,6], lastVal = 1)
        self.assertEqual(i1.valGen.generator.firstVal ,[2,4,6])
        self.assertEqual(i1.valGen.generator.lastVal , 1)
        
        val = i1.valGen.getValue(0.5, i1)
        self.assertEqual(val, [2, 3, 4])
        val = i1.valGen.getValue(0.6, i1)
        self.assertEqual(val, [1, 2, 3])
        val = i1.valGen.getValue(0.67, i1)
        self.assertEqual(val, [1, 2, 3])
        
        self.assertEqual(i1.valGen.generator.nbvar , 3)


    def test_FloatVarScalarInterpolator(self):
        kf1 = KF(0, 1.)
        kf2 = KF(20, [2.,4.,6.])
        valGen = ValueGenerator()
        i1 = Interval(kf1, kf2, valGen)
        ip = FloatVarScalarInterpolator (None, None)
        i1.setValGenGenerator(ip)

        val = i1.valGen.getValue(0.0, i1)
        firstVal = i1.valGen.generator.firstVal 
        self.assertEqual(val, firstVal)
        self.assertEqual(firstVal, [1.])
        
        val = i1.valGen.getValue(1.0, i1)
        lastVal = i1.valGen.generator.lastVal
        self.assertEqual( val, lastVal)
        self.assertEqual(sameFloatSequences(lastVal, [2.,4.,6.]), True)
        
        val = i1.valGen.getValue(0.5, i1)
        self.assertEqual(sameFloatSequences(val, [1.5, 2.5, 3.5]), True)
        val = i1.valGen.getValue(0.6, i1)
        self.assertEqual(sameFloatSequences(val,[1.60, 2.799, 4.0]), True)
        val = i1.valGen.getValue(0.67, i1)
        self.assertEqual(sameFloatSequences(val, [1.6699, 3.010, 4.34999]), True)
        
        # configure()
        i1.valGen.generator.configure(firstVal = [2.,4.,6.], lastVal = 1)
        val = i1.valGen.getValue(0.5, i1)
        self.assertEqual(sameFloatSequences(val, [1.5, 2.5, 3.5]), True)
        val = i1.valGen.getValue(0.6, i1)
        self.assertEqual(sameFloatSequences(val, [1.399, 2.200, 3.0]), True)
        val = i1.valGen.getValue(0.67, i1)
        self.assertEqual(sameFloatSequences(val,[1.330, 1.9899, 2.6499] ), True)
        self.assertEqual(i1.valGen.generator.nbvar , 3)


    def test_IntVectorInterpolator(self):
        starts = [0, 10,  -5, -15]
        ends =  [10,  0, -15,  -5]
        kf1 = KF(0, starts)
        kf2 = KF(20, ends)
        valGen = ValueGenerator()
        i1 = Interval(kf1, kf2, valGen)
        bl = BehaviorList(None, None)
        ip = IntVectorInterpolator(None, None)
        bl.addBehavior(ip)
        i1.setValGenGenerator(bl)

        val = i1.valGen.getValue(0.0, i1)
        self.assertEqual( len(val)==4,True)
        firstVal = i1.valGen.generator.firstVal 
        self.assertEqual(val, firstVal)
        self.assertEqual(firstVal, starts)
        
                        
        val = i1.valGen.getValue(1.0, i1)
        lastVal = i1.valGen.generator.lastVal 
        self.assertEqual(val, lastVal)
        self.assertEqual(lastVal, ends)

    
        val = i1.valGen.getValue(0.5, i1)
        self.assertEqual( sameIntSequences(val, [5, 5, -10, -10]),True)
        val = i1.valGen.getValue(0.32, i1)
        self.assertEqual( sameIntSequences(val, [3, 7, -8, -12]),True)
    
        val = i1.valGen.getValue(0.38, i1)
        self.assertEqual( sameIntSequences(val, [4, 6, -9, -11]),True)

        # test configure()
        ends = [10, 20, 0, 0]
        i1.valGen.generator.configure(lastVal = numpy.array(ends ))
        self.assertEqual( sameIntSequences(i1.valGen.generator.behaviors[0].valueRange, [10, 10, 5, 15]), True)
        self.assertEqual( sameIntSequences(i1.valGen.getValue(0.5, i1), [5, 15, -3, -8]), True)
        self.assertEqual( sameIntSequences(i1.valGen.getValue(0.32, i1),[3, 13, -3, -10]), True)
        self.assertEqual( sameIntSequences(i1.valGen.getValue(0.38, i1), [4, 14, -3, -9]), True)

        
    def test_FloatVectorInterpolator(self):
        starts = [0.0, 10.0,  -5.0, -15.0]
        ends =  [10.0,  0.0, -15.0,  -5.0]
        kf1 = KF(0, starts)
        kf2 = KF(20, ends)
        valGen = ValueGenerator()
        i1 = Interval(kf1, kf2, valGen)
        ip = FloatVectorInterpolator(None, None)
        i1.setValGenGenerator(ip)
        
        val = i1.valGen.getValue(0.0, i1)
        self.assertEqual( len(val)==4,True)
        firstVal = i1.valGen.generator.firstVal 
        self.assertEqual( sameFloatSequences(val, firstVal),True)
        self.assertEqual(sameFloatSequences(firstVal, starts),True)
                        
        val = i1.valGen.getValue(1.0, i1)
        lastVal = i1.valGen.generator.lastVal 
        self.assertEqual( sameFloatSequences(val, lastVal),True)
        self.assertEqual(sameFloatSequences(lastVal, ends),True)
    
        val = i1.valGen.getValue(0.5, i1)
        self.assertEqual( sameFloatSequences(val, [5.0, 5.0, -10.0, -10.0]),True)
       
        val = i1.valGen.getValue(0.32, i1)
        self.assertEqual( sameFloatSequences(val, [3.20, 6.799, -8.199, -11.80]), True)
    
        val = i1.valGen.getValue(0.38, i1)
        self.assertEqual( sameFloatSequences(val, [3.799, 6.20, -8.80, -11.199]),True)
        # test configure()
        ends = [10., 20., 0., 0.]
        i1.valGen.generator.configure(lastVal = numpy.array(ends ))
        self.assertEqual( sameFloatSequences(i1.valGen.generator.valueRange, [10.0, 10.0, 5.0, 15.0]), True)
        self.assertEqual( sameFloatSequences(i1.valGen.getValue(0.5, i1), [5, 15, -2.5, -7.5]), True)
        self.assertEqual( sameFloatSequences(i1.valGen.getValue(0.32, i1),[3.2, 13.1999, -3.3999, -10.1999]), True)
        self.assertEqual( sameFloatSequences(i1.valGen.getValue(0.38, i1), [3.7999, 13.80, -3.10, -9.30]), True)
        self.assertEqual(i1.valGen.generator.nbvar , 4)


    def test_VarVectorInterpolator(self):

        val1 = [[1,1,1], ]
        val2 = [[6,6,6], [8,8,8], [10,10,10]] 

        kf1 = KF(0, val1)
        kf2 = KF(20, val2)
        valGen = ValueGenerator()
        i1 = Interval(kf1, kf2, valGen)
        bl = BehaviorList(None, None)
        ip = VarVectorInterpolator(None, None)
        bl.addBehavior(ip)
        i1.setValGenGenerator(bl)
        
        val= i1.valGen.getValue(0., i1)
        self.assertEqual( sameFloatSequences(val,val1), True)
        firstVal = i1.valGen.generator.firstVal 
        self.assertEqual( sameFloatSequences(val, firstVal),True)
        
        val = i1.valGen.getValue(1., i1)
        self.assertEqual( sameFloatSequences(val,val2), True)
        lastVal = i1.valGen.generator.lastVal 
        self.assertEqual( sameFloatSequences(val, lastVal),True)
        
        val = i1.valGen.getValue(0.5, i1)
        self.assertEqual(type(val), numpy.ndarray)
        self.assertEqual(sameFloatSequences(val.ravel() ,
                                      numpy.array([[ 3.5,  3.5,  3.5],
                                                     [ 4.5,  4.5,  4.5],
                                                     [ 5.5,  5.5,  5.5]], 'f').ravel()), True)
        val = i1.valGen.getValue(0.6, i1)
        self.assertEqual(type(val), numpy.ndarray)
        self.assertEqual(sameFloatSequences(val.ravel() ,
                                      numpy.array([[ 4.0,  4.0,  4.0 ],
                                                     [ 5.2,  5.2,  5.2,],
                                                     [ 6.4,  6.4,  6.4,]], 'f').ravel()), True)
        val = i1.valGen.getValue(0.67, i1)
        self.assertEqual(type(val), numpy.ndarray)
        self.assertEqual(sameFloatSequences(val.ravel() ,
                                      numpy.array([[ 4.35,  4.35,  4.35],
                                                     [ 5.69,  5.69,  5.69],
                                                     [ 7.03,  7.03,  7.03]], 'f').ravel()), True)
        
        # configure()
        i1.valGen.generator.configure(firstVal = val2, lastVal = val1)
        val = i1.valGen.getValue(0.5, i1)
        self.assertEqual(type(val), numpy.ndarray)
        self.assertEqual(sameFloatSequences(val.ravel(),
                                            numpy.array([[3.5, 3.5, 3.5],
                                                           [4.5, 4.5, 4.5],
                                                           [5.5, 5.5, 5.5]], 'f').ravel()), True)

        val = i1.valGen.getValue(0.6, i1)
        self.assertEqual(type(val), numpy.ndarray)
        self.assertEqual(sameFloatSequences(val.ravel(),
                                            numpy.array([[3.0, 3.0, 3.0],
                                                           [3.8, 3.8, 3.8],
                                                           [4.6, 4.6, 4.6]], 'f').ravel()), True)

        val = i1.valGen.getValue(0.67, i1)
        self.assertEqual(type(val), numpy.ndarray)
        self.assertEqual(sameFloatSequences(val.ravel() ,
                                         numpy.array([[2.65, 2.65, 2.65],
                                                        [3.31, 3.31, 3.31],
                                                        [3.97, 3.97, 3.97]], 'f').ravel()), True) 
        
        
    def test_RotationInterpolator(self):

        val1 = [0.0, 0.0, 0.0, 1.0]
        val2 = [0.0, 1.0, 0.0, 0.0]
        kf1 = KF(0, val1)
        kf2 = KF(20, val2)
        valGen = ValueGenerator()
        i1 = Interval(kf1, kf2, valGen)
        ip = RotationInterpolator(None, None)
        i1.setValGenGenerator(ip)

        val= i1.valGen.getValue(0., i1)
        self.assertEqual( sameFloatSequences(val,val1), True)
        firstVal = i1.valGen.generator.firstVal 
        self.assertEqual( sameFloatSequences(val, firstVal),True)
        
        val = i1.valGen.getValue(1., i1)
        self.assertEqual( sameFloatSequences(val,val2), True)
        lastVal = i1.valGen.generator.lastVal 
        self.assertEqual( sameFloatSequences(val, lastVal),True)


        val = i1.valGen.getValue(0.5, i1)
        newval = [0.0, 0.7071, 0.0, 0.7071]
        self.assertEqual( sameFloatSequences(val, newval),True)
        
        # test configure()
        i1.valGen.generator.configure(lastVal = newval)
        val = i1.valGen.getValue(1., i1)
        self.assertEqual( sameFloatSequences(val, newval),True)
        val = i1.valGen.getValue(0.5, i1)
        self.assertEqual( sameFloatSequences(val, newval),False)
        


    def test_FunctionInterpolator(self):
        func1 = FunctionInterpolator(function = simple)
        val = func1.getValue(0.5, None)
        self.assertEqual(val,0.5)

        func1 = FunctionInterpolator(function = adding)
        val = func1.getValue(0.5, None)
        self.assertEqual(val,1)

        #with posArgs,namedArgs
        func1 = FunctionInterpolator( function = (withargs,(2,),{'height':340,'width':20}))
        kf1 = KF(0,  5.0)
        kf2 = KF(20, 15.0)
        valGen = ValueGenerator()
        i1 = Interval(kf1, kf2, valGen)
        i1.setValGenGenerator(func1)

        val= i1.valGen.getValue(0., i1)
        self.assertEqual(val, 68000.0)
        firstVal = i1.valGen.generator.firstVal 
        self.assertEqual(5.0, firstVal)
        
        val = i1.valGen.getValue(1., i1)
        self.assertEqual(val, 204000.0)
        lastVal = i1.valGen.generator.lastVal 
        self.assertEqual(15.0, lastVal)
        

        val = i1.valGen.getValue(0.5, i1)
        self.assertEqual(val, 136000.0)
        
        i1.valGen.generator.configure(function = simple)
        val0 = i1.valGen.getValue(0, i1)
        self.assertEqual(val0,5.0)
        val1 = i1.valGen.getValue(1, i1)
        self.assertEqual(val1, 15.0)
        val = i1.valGen.getValue(0.5, i1)
        self.assertEqual(val, 10.0)

       

    def test_CompositeInterpolator(self):

        val1 = ([1,1,1], 1,)
        val2 = ([10,10,10], 10)
        kf1 = KF(0, val1)
        kf2 = KF(20, val2)
        valGen = ValueGenerator()
        i1 = Interval(kf1, kf2, valGen)
        ip = CompositeInterpolator(None, None,
                                   interpolators = (FloatVectorInterpolator, FloatScalarInterpolator))
        i1.setValGenGenerator(ip)

        val= ip.getValue(0.5, i1)
        #print "test Comp int;, val:", val
        self.assertEqual(len(val) , 2)
        
        self.assertEqual(sameFloatSequences(val[0], [5.5, 5.5, 5.5]), True)
        self.assertEqual(val[1], 5.5)
        val = ip.getValue(0.7, i1)
        self.assertEqual(len(val) , 2)
        self.assertEqual(sameFloatSequences(val[0], [7.299, 7.299, 7.299]), True)
        self.assertEqual(sameFloatSequences([val[1]], [7.299,]), True)

        #configure()
        ip.configure(interpolators = (FloatScalarInterpolator, IntScalarInterpolator,FloatVectorInterpolator),
                     firstVal = (1.0, 1,[1,1,1]), lastVal = (10.0, 10, [10,10,10]) )
        self.assertEqual(len(ip.interpolators) , 3)
        val= ip.getValue(0.5, i1)
        self.assertEqual(len(val) , 3)
        self.assertEqual(sameFloatSequences([val[0],] ,[5.5,]), True)
        self.assertEqual(val[1], 6)
        self.assertEqual(sameFloatSequences(val[2], [5.5, 5.5, 5.5]), True)
        
        val = ip.getValue(0.7, i1)
        self.assertEqual(len(val) , 3)
        self.assertEqual(sameFloatSequences([val[0],] ,[7.2999]), True)
        self.assertEqual(val[1], 7)
        self.assertEqual(sameFloatSequences(val[2], [7.299, 7.299, 7.299]), True)
                                   
if __name__ == '__main__':
    unittest.main()
