#  Copyright (c) 2020, Manfred Moitzi
#  License: MIT License

import pytest
from ezdxf.render.forms import square, translate
from ezdxf.path import Path, nesting, from_vertices

EXTERIOR = list(translate(square(10), (-5, -5)))
EXT1_PATH = from_vertices(EXTERIOR)
EXT2_PATH = from_vertices(translate(EXTERIOR, (11, 0)))

CENTER_HOLE1 = list(translate(square(8), (-4, -4)))
CH1_PATH = from_vertices(CENTER_HOLE1)

CENTER_HOLE2 = list(translate(square(6), (-3, -3)))
CH2_PATH = from_vertices(CENTER_HOLE2)

LEFT_HOLE = list(translate(square(2.1), (-3, -1)))
LH_PATH = from_vertices(LEFT_HOLE)

RIGHT_HOLE = list(translate(square(2.0), (3, -1)))
RH_PATH = from_vertices(RIGHT_HOLE)

DETECTION_DATA = [
    pytest.param(
        # Each polygon is a list of paths
        [EXT1_PATH],
        [[EXT1_PATH]],
        id="1 path",
    ),
    pytest.param(
        # returns the path sorted by area, and reversed if equal sized
        [EXT1_PATH, EXT2_PATH],
        [[EXT2_PATH], [EXT1_PATH]],
        id="2 separated paths",
    ),
    pytest.param(
        [CH1_PATH, EXT1_PATH], [[EXT1_PATH, [CH1_PATH]]], id="1 nested sub-path"
    ),
    pytest.param(
        [CH1_PATH, EXT1_PATH, CH2_PATH],
        [[EXT1_PATH, [CH1_PATH, [CH2_PATH]]]],
        id="2 nested sub-path",
    ),
    pytest.param(
        [RH_PATH, LH_PATH, EXT1_PATH],
        [[EXT1_PATH, [LH_PATH], [RH_PATH]]],
        id="2 separated sub-paths",
    ),
]


@pytest.mark.parametrize("paths,polygons", DETECTION_DATA)
def test_fast_bbox_detection(paths, polygons):
    assert nesting.fast_bbox_detection(paths) == polygons


@pytest.mark.parametrize(
    "polygons,exp_ccw,exp_cw",
    [
        pytest.param(
            [[EXT1_PATH]],
            [EXT1_PATH],  # ccw paths
            [],  # cw paths
            id="1 polygon",
        ),
        pytest.param(
            [[EXT1_PATH], [EXT1_PATH]],
            [EXT1_PATH, EXT1_PATH],  # ccw paths
            [],  # cw paths
            id="2 polygons",
        ),
        pytest.param(
            [[EXT1_PATH, [CH1_PATH]]],
            [EXT1_PATH],  # ccw paths
            [CH1_PATH],  # cw paths
            id="1 polygon 1 nested sub-polygon",
        ),
        pytest.param(
            [[EXT1_PATH, [CH1_PATH, [CH1_PATH]]]],
            [EXT1_PATH, CH1_PATH],  # ccw paths
            [CH1_PATH],  # cw paths
            id="1 polygon 2 nested sub-polygons",
        ),
        pytest.param(
            [[EXT1_PATH, [CH1_PATH], [CH1_PATH]]],
            [EXT1_PATH],  # ccw paths
            [CH1_PATH, CH1_PATH],  # cw paths
            id="1 polygon 2 separated sub-polygons",
        ),
    ],
)
def test_winding_deconstruction(polygons, exp_ccw, exp_cw):
    ccw, cw = nesting.winding_deconstruction(polygons)
    assert ccw == exp_ccw
    assert cw == exp_cw


@pytest.mark.parametrize(
    "polygons,n",
    [
        pytest.param([[EXT1_PATH]], 1, id="1 polygon"),
        pytest.param([[EXT1_PATH], [EXT1_PATH]], 2, id="2 polygons"),
        pytest.param(
            [[EXT1_PATH, [CH1_PATH]]], 2, id="1 polygon 1 nested sub-polygon"
        ),
        pytest.param(
            [[EXT1_PATH, [CH1_PATH, [CH1_PATH]]]],
            3,
            id="1 polygon 2 nested sub-polygons",
        ),
        pytest.param(
            [[EXT1_PATH, [CH1_PATH], [CH1_PATH]]],
            3,
            id="1 polygon 2 separated sub-polygons",
        ),
        pytest.param(
            [[EXT1_PATH, [CH1_PATH, [CH2_PATH]], [CH1_PATH, [CH2_PATH]]]],
            5,
            id="1 polygon 2 separated nested sub-polygons",
        ),
    ],
)
def test_flatten_polygons(polygons, n):
    nlists = 0
    npaths = 0
    for path in list(nesting.flatten_polygons(polygons)):
        if isinstance(path, Path):
            npaths += 1
        elif isinstance(path, list):
            nlists += 1
        else:
            raise TypeError("?")

    assert nlists == 0
    assert npaths == n


if __name__ == "__main__":
    pytest.main([__file__])
