import pytest
from PySide2.QtGui import QVector3D

from nexus_constructor.model.component import Component
from nexus_constructor.model.dataset import Dataset
from nexus_constructor.model.instrument import Instrument
from nexus_constructor.model.value_type import ValueTypes

values = Dataset(
    name="scalar_value",
    type=ValueTypes.DOUBLE,
    size=[1],
    values=90.0,
    parent_node=None,
)


@pytest.fixture
def instrument():
    return Instrument(parent_node=None)


def test_remove_from_beginning_1(instrument):
    component1 = Component("component1", instrument)
    rot = component1.add_rotation(
        name="rotation1",
        axis=QVector3D(1.0, 0.0, 0.0),
        angle=values.values,
        values=values,
    )
    component1.depends_on = rot
    assert len(rot.dependents) == 1
    rot.remove_from_dependee_chain()
    assert component1.depends_on is None


def test_remove_from_beginning_2(instrument):
    component1 = Component("component1", instrument)
    rot1 = component1.add_rotation(
        name="rotation1",
        axis=QVector3D(1.0, 0.0, 0.0),
        angle=values.values,
        values=values,
    )
    rot2 = component1.add_rotation(
        name="rotation2",
        axis=QVector3D(1.0, 0.0, 0.0),
        angle=values.values,
        values=values,
    )
    component1.depends_on = rot1
    rot1.depends_on = rot2
    assert len(rot2.dependents) == 1
    rot1.remove_from_dependee_chain()
    assert len(rot2.dependents) == 1
    assert rot2.dependents[0] == component1
    assert component1.depends_on == rot2


def test_remove_from_beginning_3(instrument):
    component1 = Component("component1", instrument)
    component2 = Component("component2", instrument)
    rot1 = component1.add_rotation(
        name="rotation1",
        axis=QVector3D(1.0, 0.0, 0.0),
        angle=values.values,
        values=values,
    )
    rot2 = component2.add_rotation(
        name="rotation2",
        axis=QVector3D(1.0, 0.0, 0.0),
        angle=values.values,
        values=values,
    )
    component1.depends_on = rot1
    component2.depends_on = rot2
    rot1.depends_on = rot2
    assert len(rot2.dependents) == 2
    rot1.remove_from_dependee_chain()
    assert len(rot2.dependents) == 2
    assert component2 in rot2.dependents
    assert component1 in rot2.dependents
    assert component1.depends_on == rot2
    assert component1.transforms.link.linked_component == component2


def test_remove_from_middle():
    component1 = Component("component1", instrument)
    component2 = Component("component2", instrument)
    component3 = Component("component3", instrument)
    rot1 = component1.add_rotation(
        name="rotation1",
        axis=QVector3D(1.0, 0.0, 0.0),
        angle=values.values,
        values=values,
    )
    rot2 = component2.add_rotation(
        name="rotation2",
        axis=QVector3D(1.0, 0.0, 0.0),
        angle=values.values,
        values=values,
    )
    rot3 = component3.add_rotation(
        name="rotation3",
        axis=QVector3D(1.0, 0.0, 0.0),
        angle=values.values,
        values=values,
    )
    component1.depends_on = rot1
    component2.depends_on = rot2
    component3.depends_on = rot3

    component1.transforms.link.linked_component = component2
    component2.transforms.link.linked_component = component3
    rot2.remove_from_dependee_chain()
    assert rot1.depends_on == rot3
    assert component1.transforms.link.linked_component == component3
    assert rot1 in rot3.dependents
    assert component3 in rot3.dependents


def test_remove_from_end():
    component1 = Component("component1", instrument)
    rot1 = component1.add_rotation(
        name="rotation1",
        axis=QVector3D(1.0, 0.0, 0.0),
        angle=values.values,
        values=values,
    )
    rot2 = component1.add_rotation(
        name="rotation2",
        axis=QVector3D(1.0, 0.0, 0.0),
        angle=values.values,
        values=values,
        depends_on=rot1,
    )
    rot3 = component1.add_rotation(
        name="rotation3",
        axis=QVector3D(1.0, 0.0, 0.0),
        angle=values.values,
        values=values,
        depends_on=rot2,
    )

    component1.depends_on = rot3

    rot1.remove_from_dependee_chain()

    assert rot1.depends_on is None
    assert not rot1.dependents

    assert component1.depends_on == rot3

    assert rot2.dependents[0] == rot3
    assert len(component1.transforms) == 2

[((9, 9, 15, 1), 'nexus_constructor.model.dataset.Dataset', 'Dataset', (), '', False, 'from nexus_constructor.model.dataset import Dataset\n'), ((20, 11, 20, 39), 'nexus_constructor.model.instrument.Instrument', 'Instrument', (), '', False, 'from nexus_constructor.model.instrument import Instrument\n'), ((24, 17, 24, 52), 'nexus_constructor.model.component.Component', 'Component', ({(24, 27, 24, 39): '"""component1"""', (24, 41, 24, 51): 'instrument'}, {}), "('component1', instrument)", False, 'from nexus_constructor.model.component import Component\n'), ((38, 17, 38, 52), 'nexus_constructor.model.component.Component', 'Component', ({(38, 27, 38, 39): '"""component1"""', (38, 41, 38, 51): 'instrument'}, {}), "('component1', instrument)", False, 'from nexus_constructor.model.component import Component\n'), ((61, 17, 61, 52), 'nexus_constructor.model.component.Component', 'Component', ({(61, 27, 61, 39): '"""component1"""', (61, 41, 61, 51): 'instrument'}, {}), "('component1', instrument)", False, 'from nexus_constructor.model.component import Component\n'), ((62, 17, 62, 52), 'nexus_constructor.model.component.Component', 'Component', ({(62, 27, 62, 39): '"""component2"""', (62, 41, 62, 51): 'instrument'}, {}), "('component2', instrument)", False, 'from nexus_constructor.model.component import Component\n'), ((88, 17, 88, 52), 'nexus_constructor.model.component.Component', 'Component', ({(88, 27, 88, 39): '"""component1"""', (88, 41, 88, 51): 'instrument'}, {}), "('component1', instrument)", False, 'from nexus_constructor.model.component import Component\n'), ((89, 17, 89, 52), 'nexus_constructor.model.component.Component', 'Component', ({(89, 27, 89, 39): '"""component2"""', (89, 41, 89, 51): 'instrument'}, {}), "('component2', instrument)", False, 'from nexus_constructor.model.component import Component\n'), ((90, 17, 90, 52), 'nexus_constructor.model.component.Component', 'Component', ({(90, 27, 90, 39): '"""component3"""', (90, 41, 90, 51): 'instrument'}, {}), "('component3', instrument)", False, 'from nexus_constructor.model.component import Component\n'), ((123, 17, 123, 52), 'nexus_constructor.model.component.Component', 'Component', ({(123, 27, 123, 39): '"""component1"""', (123, 41, 123, 51): 'instrument'}, {}), "('component1', instrument)", False, 'from nexus_constructor.model.component import Component\n'), ((27, 13, 27, 37), 'PySide2.QtGui.QVector3D', 'QVector3D', ({(27, 23, 27, 26): '1.0', (27, 28, 27, 31): '0.0', (27, 33, 27, 36): '0.0'}, {}), '(1.0, 0.0, 0.0)', False, 'from PySide2.QtGui import QVector3D\n'), ((41, 13, 41, 37), 'PySide2.QtGui.QVector3D', 'QVector3D', ({(41, 23, 41, 26): '1.0', (41, 28, 41, 31): '0.0', (41, 33, 41, 36): '0.0'}, {}), '(1.0, 0.0, 0.0)', False, 'from PySide2.QtGui import QVector3D\n'), ((47, 13, 47, 37), 'PySide2.QtGui.QVector3D', 'QVector3D', ({(47, 23, 47, 26): '1.0', (47, 28, 47, 31): '0.0', (47, 33, 47, 36): '0.0'}, {}), '(1.0, 0.0, 0.0)', False, 'from PySide2.QtGui import QVector3D\n'), ((65, 13, 65, 37), 'PySide2.QtGui.QVector3D', 'QVector3D', ({(65, 23, 65, 26): '1.0', (65, 28, 65, 31): '0.0', (65, 33, 65, 36): '0.0'}, {}), '(1.0, 0.0, 0.0)', False, 'from PySide2.QtGui import QVector3D\n'), ((71, 13, 71, 37), 'PySide2.QtGui.QVector3D', 'QVector3D', ({(71, 23, 71, 26): '1.0', (71, 28, 71, 31): '0.0', (71, 33, 71, 36): '0.0'}, {}), '(1.0, 0.0, 0.0)', False, 'from PySide2.QtGui import QVector3D\n'), ((93, 13, 93, 37), 'PySide2.QtGui.QVector3D', 'QVector3D', ({(93, 23, 93, 26): '1.0', (93, 28, 93, 31): '0.0', (93, 33, 93, 36): '0.0'}, {}), '(1.0, 0.0, 0.0)', False, 'from PySide2.QtGui import QVector3D\n'), ((99, 13, 99, 37), 'PySide2.QtGui.QVector3D', 'QVector3D', ({(99, 23, 99, 26): '1.0', (99, 28, 99, 31): '0.0', (99, 33, 99, 36): '0.0'}, {}), '(1.0, 0.0, 0.0)', False, 'from PySide2.QtGui import QVector3D\n'), ((105, 13, 105, 37), 'PySide2.QtGui.QVector3D', 'QVector3D', ({(105, 23, 105, 26): '1.0', (105, 28, 105, 31): '0.0', (105, 33, 105, 36): '0.0'}, {}), '(1.0, 0.0, 0.0)', False, 'from PySide2.QtGui import QVector3D\n'), ((126, 13, 126, 37), 'PySide2.QtGui.QVector3D', 'QVector3D', ({(126, 23, 126, 26): '1.0', (126, 28, 126, 31): '0.0', (126, 33, 126, 36): '0.0'}, {}), '(1.0, 0.0, 0.0)', False, 'from PySide2.QtGui import QVector3D\n'), ((132, 13, 132, 37), 'PySide2.QtGui.QVector3D', 'QVector3D', ({(132, 23, 132, 26): '1.0', (132, 28, 132, 31): '0.0', (132, 33, 132, 36): '0.0'}, {}), '(1.0, 0.0, 0.0)', False, 'from PySide2.QtGui import QVector3D\n'), ((139, 13, 139, 37), 'PySide2.QtGui.QVector3D', 'QVector3D', ({(139, 23, 139, 26): '1.0', (139, 28, 139, 31): '0.0', (139, 33, 139, 36): '0.0'}, {}), '(1.0, 0.0, 0.0)', False, 'from PySide2.QtGui import QVector3D\n')]