from Scenario2.keyframes import ValueObject, ValueGenerator,KF, Interval, AutoCurrentValueObject , KFAutoCurrentValue
from Scenario2.interpolators import FloatScalarInterpolator

def test_001KFvalue1():
    """
    test ValueObject object contructor, setting and getting its value
    """
    # create object with no value
    obj = ValueObject()
    assert obj.getValue()==None

    obj.setValue(6)
    assert obj.getValue()==6

    obj.setValue('Hello World')
    assert obj.getValue()=='Hello World'

    # create object with passing value
    obj = ValueObject(6)
    assert obj.getValue()==6

    obj= ValueObject('Hello World')
    assert obj.getValue()=='Hello World'


def test_002ValueGenerator1():
    """
    test the creation of a value generator object
    """
    # create object with no value
    obj = ValueGenerator()
    try:
        obj.getValue(0.5, None)
    except ValueError:
        pass

    def f(percent, interval=None):
        return percent*2

    obj.setGenerator(f)
    assert obj.getValue(2, None)==4


def test_002ValueGenerator2():
    # create object with no value
    obj = ValueGenerator()

    # clone the ValueGenerator with no generator
    obj1 = obj.clone()
    assert isinstance(obj1, obj.__class__)
    assert obj.generator == obj1.generator

    def f(percent):
        return percent*2

    obj.setGenerator(f)
    assert obj.generator == f

    #clone the ValueGenerator with function
    obj1 = obj.clone()
    assert isinstance(obj1, obj.__class__)
    assert obj.generator == obj1.generator

    #clone the ValueGenerator with generator support clone() method
    gen = FloatScalarInterpolator(None, None)
    obj.setGenerator(gen)
    assert obj.generator == gen
    obj1 = obj.clone()
    assert isinstance(obj1, obj.__class__)
    assert obj.generator != obj1.generator
    assert obj.generator == gen
    

def test_003KF1():
    """
    test KF contructor
    """

    # KF requires position when created
    try:
        kf = KF()
    except TypeError:
        pass

    # with position but no value
    kf = KF(0, None)
    assert kf.pos == 0
    # we expect AttributeError if we try to get the value
    try:
        assert kf.getValue() == None
    except AttributeError:
        pass
    
    # with position and value is a simple value
    kf = KF(5, 7)
    assert kf.pos == 5
    assert kf.getValue() == 7

    # with position and value is a ValueObject
    kv = ValueObject('Hello')
    kf = KF(5, kv)
    
    assert kf.pos == 5
    assert kf.getValue() == 'Hello'

    # create second keyframe with same ValueObject
    kf1 = KF(12, kv)
    assert kf1.pos == 12
    assert kf1.getValue() == 'Hello'

    # make sure that if we change the value in kv both KF see the change
    kv.setValue('Bye')
    assert kf.getValue()=='Bye'
    assert kf1.getValue()=='Bye'


def test_004linkedKF1():
    """
    test that linked KFs are build properly and can be retrieved
    """
    # get a linked copy of a keyframe
    kf1 = KF(10, 10)
    kf2 = kf1.linkedCopy(15)
    assert kf2.pos == 15
    assert kf2.getValue() == 10
    assert kf1.nxtLinked == kf2
    assert kf1.prvLinked == None
    assert kf2.prvLinked == kf1
    assert kf2.nxtLinked == None

    # make sure either of the 2 KF can set the value
    kf1.setValue( 32 )
    assert kf1.getValue() == 32
    assert kf2.getValue() == 32

    kf2.setValue( 28 )
    assert kf1.getValue() == 28
    assert kf2.getValue() == 28

    # get a linked copy of kf2
    kf3 = kf2.linkedCopy(20)

    # get another copy of kf1
    kf4 = kf1.linkedCopy(16)

    # get all linked KFs
    lkf = kf1.getAllLinked()
    assert len(lkf)==4
    assert kf1==lkf[0]
    assert kf2 in lkf
    assert kf3 in lkf
    assert kf4 in lkf

    lkf = kf2.getAllLinked()
    assert len(lkf)==4
    assert kf2==lkf[0]
    assert kf1 in lkf
    assert kf3 in lkf
    assert kf4 in lkf

    lkf = kf3.getAllLinked()
    assert len(lkf)==4
    assert kf3==lkf[0]
    assert kf1 in lkf
    assert kf2 in lkf
    assert kf4 in lkf

    lkf = kf4.getAllLinked()
    assert len(lkf)==4
    assert kf4==lkf[0]
    assert kf1 in lkf
    assert kf2 in lkf
    assert kf3 in lkf


def test_005KFcopy():
    """
    test creating a copy of a keyframe
    """
    kf1 = KF(10, 10)
    kf2 = kf1.copy(15)
    assert kf2.pos == 15
    assert kf2.getValue() == 10
    assert kf2.valueObject != kf1.valueObject
    kf2.setValue(30)
    assert kf2.getValue() == 30
    assert kf1.getValue() == 10
   
    
def test_005Interval1():
    """
    test Interval constructor
    """
    i1 = Interval()
    assert i1.kf1 is None
    assert i1.kf2 is None
    assert isinstance(i1.valGen, ValueGenerator)

    kf1 = KF(0, 0)
    i1 = Interval(kf1)
    assert i1.kf1 == kf1
    assert i1.kf2 is None
    assert isinstance(i1.valGen, ValueGenerator)

    kf2 = KF(10, 10)
    i1 = Interval(kf1, kf2)
    assert i1.kf1 == kf1
    assert i1.kf2 == kf2
    assert isinstance(i1.valGen, ValueGenerator)

    vg = ValueGenerator()
    i1 = Interval(kf1, kf2, vg)
    assert i1.kf1 == kf1
    assert i1.kf2 == kf2
    assert i1.valGen == vg
    

def test_006intervalLinked1():
    """
    test creating linked Interval 
    """
    kf1 = KF(0, 10)
    kf2 = KF(10, 0)
    i1 = Interval(kf1, kf2)
    i2 = i1.linkedCopy(20)
    
    assert i2.kf1.pos == 20
    assert i2.kf2.pos == 30
    assert i2.valGen == i2.valGen

    i3 = i2.linkedCopy(40)
    assert i3.kf1.pos == 40
    assert i3.kf2.pos == 50
    assert i3.valGen == i2.valGen
    assert i3.valGen == i1.valGen

    li = i1.getAllLinked()
    assert len(li) == 3
    assert li[0] == i1
    assert i2 in li
    assert i3 in li

    li = i2.getAllLinked()
    assert len(li) == 3
    assert li[0] == i2
    assert i1 in li
    assert i3 in li
    

def test_007intervalValGen():
    kf1 = KF(0, 0)
    kf2 = KF(10, 10)
    valGen = ValueGenerator()
    i1 = Interval(kf1, kf2, valGen)

    gen = FloatScalarInterpolator(None, None)
    i1.setValGenGenerator(gen)

    assert i1.getValue(0) == 0.0
    assert i1.getValue(10) == 10.0
    assert i1.getValue(5) == 5.0

    i1 = Interval(kf1, None, valGen)
    assert i1.getValue(10) == 0.0
    assert i1.getValue(100) == 0.0



def test_008KFAutoCurrentValue():
    """Test creation KFAutoCurrentValue keyframe with AutoCurrentValueObject object """
    class Object:

        def __init__(self, val):
            self.value = val

        def get(self):
            return self.value

        def set(self, value):
            self.value = value

    obj = Object(5)
    from Scenario2.actor import CustomActor
    actor = CustomActor('obj', obj, setMethod='set',
                        getFunction=(obj.get, (), {}))

    autoval = AutoCurrentValueObject(actor)
    kf = KFAutoCurrentValue(0, autoval)
    assert kf.getValue() == 5
    
