# Copyright (c) 2010-2020 Manfred Moitzi
# License: MIT License
import pytest
from ezdxf.math import Bezier, Matrix44

DEFPOINTS2D = [
    (0.0, 0.0, 0.0),
    (3.0, 0.0, 0.0),
    (7.0, 10.0, 0.0),
    (10.0, 10.0, 0.0),
]
DEFPOINTS3D = [
    (0.0, 0.0, 0.0),
    (10.0, 20.0, 20.0),
    (30.0, 10.0, 25.0),
    (40.0, 10.0, 25.0),
    (50.0, 0.0, 30.0),
]


def test_points_2d():
    bcurve = Bezier(DEFPOINTS2D)
    for index, chk in enumerate(POINTS2D):
        assert bcurve.point(index * 0.1).isclose(chk)


def test_bezier_objects_are_immutable():
    curve = Bezier(DEFPOINTS3D)
    with pytest.raises(TypeError):
        curve.control_points[0] = (1, 2, 3)


def test_point_and_tangent_2d():
    dbcurve = Bezier(DEFPOINTS2D)
    for index, (chk_pnt, chk_d1) in enumerate(zip(POINTS2D, TANGENTS2D)):
        pnt, d1, d2 = dbcurve.derivative(index * 0.1)
        assert pnt.isclose(chk_pnt)
        assert d1.isclose(chk_d1)


def test_points_3d():
    bcurve = Bezier(DEFPOINTS3D)
    points = list(bcurve.approximate(40))

    for point, chk in zip(points, iter_dbezier(DBEZIER3D, 0)):
        assert point.isclose(chk)


@pytest.fixture(scope="module")
def dbezier():
    curve = Bezier(DEFPOINTS3D)
    return list(curve.derivatives(curve.params(40)))


def iter_data(result, n):
    return zip(iter_dbezier(result, n), iter_dbezier(DBEZIER3D, n))


def iter_dbezier(values, n):
    return (data[n] for data in values)


def test_points(dbezier):
    for point, chk in iter_data(dbezier, 0):
        assert point.isclose(chk)


def test_derivative_1(dbezier):
    for point, chk in iter_data(dbezier, 1):
        assert point.isclose(chk)


def test_derivative_2(dbezier):
    for point, chk in iter_data(dbezier, 2):
        assert point.isclose(chk, abs_tol=1e-10)


def test_reverse():
    curve = Bezier(DEFPOINTS3D)
    new = curve.reverse()
    assert curve.control_points[0] == new.control_points[-1]


def test_transform_interface():
    curve = Bezier(DEFPOINTS3D)
    new = curve.transform(Matrix44.translate(1, 2, 3))
    assert new.control_points[0] == curve.control_points[0] + (1, 2, 3)


def test_flattening():
    curve = Bezier([(0, 0), (1, 1), (2, -1), (3, 0)])
    assert len(list(curve.flattening(1.0, segments=4))) == 5
    assert len(list(curve.flattening(0.1, segments=4))) == 7


POINTS2D = [
    (0.000, 0.000),
    (0.928, 0.280),
    (1.904, 1.040),
    (2.916, 2.160),
    (3.952, 3.520),
    (5.000, 5.000),
    (6.048, 6.480),
    (7.084, 7.840),
    (8.096, 8.960),
    (9.072, 9.720),
    (10.00, 10.00),
]

TANGENTS2D = [
    (9.0, 0.0),
    (9.5400000000000009, 5.3999999999999995),
    (9.9600000000000009, 9.6000000000000014),
    (10.26, 12.600000000000001),
    (10.440000000000001, 14.4),
    (10.5, 15.0),
    (10.44, 14.399999999999999),
    (10.260000000000002, 12.600000000000001),
    (9.9599999999999973, 9.5999999999999925),
    (9.5399999999999974, 5.399999999999995),
    (9.0, 0.0),
]

DBEZIER3D = [
    [[0.0, 0.0, 0.0], [40.0, 80.0, 80.0], [120.0, -360.0, -180.0]],
    [
        [1.03626171875, 1.8899765624999998, 1.9443749999999997],
        [42.85187499999999, 71.29625, 75.575],
        [108.22500000000025, -336.4499999999995, -173.99999999999946],
    ],
    [
        [2.1401875, 3.569625, 3.78],
        [45.41499999999999, 63.169999999999995, 71.3],
        [96.90000000000015, -313.7999999999997, -167.9999999999997],
    ],
    [
        [3.304699218750001, 5.053101562500001, 5.510625000000001],
        [47.700624999999995, 55.598749999999995, 67.17499999999998],
        [86.02499999999996, -292.05, -162.00000000000009],
    ],
    [
        [4.523000000000001, 6.354, 7.140000000000001],
        [49.72, 48.559999999999995, 63.199999999999996],
        [75.60000000000008, -271.2, -155.99999999999997],
    ],
    [
        [5.78857421875, 7.4853515625, 8.671875],
        [51.484375, 42.03125, 59.375],
        [65.625, -251.25, -150.0],
    ],
    [
        [7.095187500000001, 8.459625, 10.110000000000001],
        [53.004999999999995, 35.989999999999995, 55.7],
        [56.099999999999994, -232.19999999999996, -144.0],
    ],
    [
        [8.436886718750001, 9.288726562499999, 11.458125],
        [54.293124999999996, 30.413749999999993, 52.175],
        [47.02499999999992, -214.05, -138.00000000000003],
    ],
    [
        [9.808000000000005, 9.984000000000004, 12.720000000000004],
        [55.360000000000014, 25.280000000000005, 48.80000000000001],
        [38.40000000000002, -196.79999999999995, -131.99999999999997],
    ],
    [
        [11.20313671875, 10.556226562500003, 13.899375000000003],
        [56.216875000000016, 20.56625, 45.575],
        [30.225000000000033, -180.45, -126.0],
    ],
    [
        [12.6171875, 11.015625, 15.0],
        [56.875, 16.25, 42.5],
        [22.5, -165.0, -120.0],
    ],
    [
        [14.045324218750004, 11.371851562500003, 16.025625000000005],
        [57.345625000000005, 12.308749999999996, 39.575],
        [15.225000000000001, -150.45, -113.99999999999999],
    ],
    [
        [15.483000000000004, 11.634, 16.98],
        [57.640000000000015, 8.719999999999995, 36.8],
        [8.399999999999977, -136.79999999999998, -107.99999999999997],
    ],
    [
        [16.925949218750002, 11.8106015625, 17.866875000000004],
        [57.769375000000004, 5.461249999999998, 34.175],
        [2.024999999999949, -124.05000000000004, -102.00000000000003],
    ],
    [
        [18.3701875, 11.909624999999998, 18.689999999999998],
        [57.745000000000005, 2.509999999999998, 31.700000000000003],
        [-3.90000000000002, -112.19999999999999, -96.00000000000001],
    ],
    [
        [19.81201171875, 11.9384765625, 19.453125],
        [57.578125, -0.15625, 29.375],
        [-9.375, -101.25, -90.0],
    ],
    [
        [21.248000000000005, 11.904, 20.160000000000004],
        [57.28000000000001, -2.5599999999999987, 27.200000000000003],
        [-14.400000000000048, -91.19999999999999, -84.00000000000003],
    ],
    [
        [22.675011718750003, 11.812476562499999, 20.814375],
        [56.86187499999999, -4.723750000000006, 25.174999999999994],
        [-18.97500000000001, -82.04999999999997, -78.00000000000001],
    ],
    [
        [24.090187500000006, 11.669625000000003, 21.420000000000005],
        [56.335, -6.670000000000007, 23.299999999999997],
        [-23.09999999999998, -73.8, -71.99999999999997],
    ],
    [
        [25.49094921875, 11.480601562499999, 21.980624999999996],
        [55.71062500000001, -8.42125, 21.575000000000003],
        [-26.774999999999977, -66.44999999999997, -65.99999999999996],
    ],
    [[26.875, 11.25, 22.5], [55.0, -10.0, 20.0], [-30.0, -60.0, -60.0]],
    [
        [28.240324218750004, 10.981851562500001, 22.981875],
        [54.214375000000004, -11.42875, 18.575],
        [-32.77499999999998, -54.44999999999999, -53.99999999999997],
    ],
    [
        [29.585187500000004, 10.679625000000001, 23.43],
        [53.365, -12.73, 17.3],
        [-35.10000000000005, -49.8, -47.999999999999986],
    ],
    [
        [30.90813671875, 10.346226562499997, 23.848125],
        [52.46312499999999, -13.926250000000003, 16.174999999999997],
        [-36.97499999999994, -46.04999999999998, -41.99999999999996],
    ],
    [
        [32.208000000000006, 9.983999999999998, 24.24],
        [51.519999999999996, -15.040000000000003, 15.199999999999996],
        [-38.39999999999992, -43.19999999999997, -35.99999999999994],
    ],
    [
        [33.48388671875, 9.5947265625, 24.609375],
        [50.546875, -16.09375, 14.375],
        [-39.375, -41.25, -30.0],
    ],
    [
        [34.7351875, 9.179624999999998, 24.96],
        [49.555000000000014, -17.11, 13.700000000000003],
        [-39.900000000000034, -40.199999999999996, -24.0],
    ],
    [
        [35.96157421875, 8.7393515625, 25.295625],
        [48.555625, -18.111250000000002, 13.174999999999997],
        [-39.974999999999966, -40.05, -18.0],
    ],
    [
        [37.163000000000004, 8.273999999999997, 25.62],
        [47.56, -19.120000000000005, 12.800000000000011],
        [-39.60000000000002, -40.80000000000001, -12.0],
    ],
    [
        [38.339699218750006, 7.783101562499999, 25.936875],
        [46.579375, -20.158750000000005, 12.575000000000003],
        [-38.77500000000009, -42.450000000000045, -6.000000000000028],
    ],
    [
        [39.4921875, 7.265625, 26.25],
        [45.625, -21.25, 12.5],
        [-37.5, -45.0, 0.0],
    ],
    [
        [40.621261718750006, 6.7199765625, 26.563125],
        [44.70812499999998, -22.416250000000005, 12.574999999999989],
        [-35.775000000000205, -48.45000000000004, 5.999999999999915],
    ],
    [
        [41.728, 6.143999999999999, 26.880000000000003],
        [43.84, -23.680000000000003, 12.799999999999997],
        [-33.600000000000534, -52.8000000000001, 11.999999999999687],
    ],
    [
        [42.81376171875, 5.534976562499999, 27.204375],
        [43.031875, -25.063750000000006, 13.174999999999997],
        [-30.975000000000136, -58.05000000000007, 17.999999999999915],
    ],
    [
        [43.880187500000005, 4.889624999999998, 27.54],
        [42.295, -26.590000000000003, 13.70000000000001],
        [-27.900000000000148, -64.20000000000002, 23.999999999999943],
    ],
    [
        [44.92919921875, 4.2041015625, 27.890625],
        [41.640625, -28.28125, 14.375],
        [-24.375, -71.25, 30.0],
    ],
    [
        [45.962999999999994, 3.4739999999999993, 28.259999999999998],
        [41.08, -30.16, 15.200000000000017],
        [-20.39999999999884, -79.19999999999987, 36.000000000000625],
    ],
    [
        [46.98407421875, 2.6943515624999983, 28.651875],
        [40.624375, -32.24875, 16.174999999999997],
        [-15.975000000000364, -88.05000000000001, 41.999999999999886],
    ],
    [
        [47.9951875, 1.8596249999999979, 29.07],
        [40.285, -34.57000000000001, 17.299999999999983],
        [-11.09999999999377, -97.79999999999993, 48.00000000000381],
    ],
    [
        [48.99938671875, 0.9637265624999967, 29.518125],
        [40.073124999999976, -37.146250000000016, 18.575000000000003],
        [-5.775000000008845, -108.4500000000002, 53.999999999994714],
    ],
    [[50.0, 0.0, 30.0], [40.0, -40.0, 20.0], [0.0, -120.0, 60.0]],
]
