from utils import *

from sensationdriver.pattern import BezierPath
from sensationdriver.pattern import Track


class Point(object):
    def __init__(self, time, value):
        self.time = time
        self.value = value


class Keyframe(object):
    def __init__(self, control_point, out_tangent_end=None, in_tangent_start=None):
        self.control_point = control_point
        self.out_tangent_end = out_tangent_end
        self.in_tangent_start = in_tangent_start


class TestBezierPath(unittest.TestCase):
    def setUp(self):
        self.logger = TestLogger()

    def test_bezier_calculation(self):
        start = Point(0, 0)
        end = Point(1.8, 2)

        start_out_tangent_end = Point(0.6, 0)
        end_in_tangent_start = Point(1.2, -1.279795)

        expected_values = [
            (0.0, 0.0),
            (0.055555, -0.01084869),
            (0.111111, -0.03938968),
            (0.166666, -0.0796154),
            (0.222222, -0.1255182),
            (0.277777, -0.1710906),
            (0.333333, -0.2103248),
            (0.388888, -0.2372134),
            (0.444444, -0.2457487),
            (0.5, -0.2299231),
            (0.555555, -0.1837291),
            (0.611111, -0.101159),
            (0.666666, 0.02379485),
            (0.722222, 0.1971399),
            (0.777777, 0.4248839),
            (0.833333, 0.7130347),
            (0.888888, 1.067599),
            (0.944444, 1.494586),
            (1.0, 2)]

        for t, expected_value in expected_values:
            value = BezierPath.calculate_bezier_value(t, start, start_out_tangent_end, end_in_tangent_start, end)
            self.assertAlmostEqual(value, expected_value, delta=0.00001)

    def test_timeline(self):
        start = Point(0, 0)
        end = Point(1.8, 2)

        start_out_tangent_end = Point(0.6, 0)
        end_in_tangent_start = Point(1.2, -1.279795)

        keyframes = [Keyframe(start, out_tangent_end=start_out_tangent_end), Keyframe(end, in_tangent_start=end_in_tangent_start)]

        path = BezierPath(keyframes=keyframes)

        expected_values = [
            0.0,
            -0.01084869,
            -0.03938968,
            -0.0796154,
            -0.1255182,
            -0.1710906,
            -0.2103248,
            -0.2372134,
            -0.2457487,
            -0.2299231,
            -0.1837291,
            -0.101159,
            0.02379485,
            0.1971399,
            0.4248839,
            0.7130347,
            1.067599,
            1.494586]

        # preparation
        timeline = path.timeline()
        next(timeline)
        i = 0
        value = timeline.send(0)
        while True:
            self.assertAlmostEqual(value, expected_values[i], delta=0.00001)
            try:
                value = timeline.send(0.1)
                i += 1
            except StopIteration:
                break

    def test_multiple_keyframes(self):