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

[((285, 382), 'nexus_constructor.model.dataset.Dataset', 'Dataset', ([], {'name': '"""scalar_value"""', 'type': 'ValueTypes.DOUBLE', 'size': '[1]', 'values': '(90.0)', 'parent_node': 'None'}), "(name='scalar_value', type=ValueTypes.DOUBLE, size=[1], values=90.0,\n    parent_node=None)\n", (292, 382), False, 'from nexus_constructor.model.dataset import Dataset\n'), ((449, 477), 'nexus_constructor.model.instrument.Instrument', 'Instrument', ([], {'parent_node': 'None'}), '(parent_node=None)\n', (459, 477), False, 'from nexus_constructor.model.instrument import Instrument\n'), ((543, 578), 'nexus_constructor.model.component.Component', 'Component', (['"""component1"""', 'instrument'], {}), "('component1', instrument)\n", (552, 578), False, 'from nexus_constructor.model.component import Component\n'), ((948, 983), 'nexus_constructor.model.component.Component', 'Component', (['"""component1"""', 'instrument'], {}), "('component1', instrument)\n", (957, 983), False, 'from nexus_constructor.model.component import Component\n'), ((1624, 1659), 'nexus_constructor.model.component.Component', 'Component', (['"""component1"""', 'instrument'], {}), "('component1', instrument)\n", (1633, 1659), False, 'from nexus_constructor.model.component import Component\n'), ((1677, 1712), 'nexus_constructor.model.component.Component', 'Component', (['"""component2"""', 'instrument'], {}), "('component2', instrument)\n", (1686, 1712), False, 'from nexus_constructor.model.component import Component\n'), ((2478, 2513), 'nexus_constructor.model.component.Component', 'Component', (['"""component1"""', 'instrument'], {}), "('component1', instrument)\n", (2487, 2513), False, 'from nexus_constructor.model.component import Component\n'), ((2531, 2566), 'nexus_constructor.model.component.Component', 'Component', (['"""component2"""', 'instrument'], {}), "('component2', instrument)\n", (2540, 2566), False, 'from nexus_constructor.model.component import Component\n'), ((2584, 2619), 'nexus_constructor.model.component.Component', 'Component', (['"""component3"""', 'instrument'], {}), "('component3', instrument)\n", (2593, 2619), False, 'from nexus_constructor.model.component import Component\n'), ((3584, 3619), 'nexus_constructor.model.component.Component', 'Component', (['"""component1"""', 'instrument'], {}), "('component1', instrument)\n", (3593, 3619), False, 'from nexus_constructor.model.component import Component\n'), ((653, 677), 'PySide2.QtGui.QVector3D', 'QVector3D', (['(1.0)', '(0.0)', '(0.0)'], {}), '(1.0, 0.0, 0.0)\n', (662, 677), False, 'from PySide2.QtGui import QVector3D\n'), ((1059, 1083), 'PySide2.QtGui.QVector3D', 'QVector3D', (['(1.0)', '(0.0)', '(0.0)'], {}), '(1.0, 0.0, 0.0)\n', (1068, 1083), False, 'from PySide2.QtGui import QVector3D\n'), ((1218, 1242), 'PySide2.QtGui.QVector3D', 'QVector3D', (['(1.0)', '(0.0)', '(0.0)'], {}), '(1.0, 0.0, 0.0)\n', (1227, 1242), False, 'from PySide2.QtGui import QVector3D\n'), ((1788, 1812), 'PySide2.QtGui.QVector3D', 'QVector3D', (['(1.0)', '(0.0)', '(0.0)'], {}), '(1.0, 0.0, 0.0)\n', (1797, 1812), False, 'from PySide2.QtGui import QVector3D\n'), ((1947, 1971), 'PySide2.QtGui.QVector3D', 'QVector3D', (['(1.0)', '(0.0)', '(0.0)'], {}), '(1.0, 0.0, 0.0)\n', (1956, 1971), False, 'from PySide2.QtGui import QVector3D\n'), ((2695, 2719), 'PySide2.QtGui.QVector3D', 'QVector3D', (['(1.0)', '(0.0)', '(0.0)'], {}), '(1.0, 0.0, 0.0)\n', (2704, 2719), False, 'from PySide2.QtGui import QVector3D\n'), ((2854, 2878), 'PySide2.QtGui.QVector3D', 'QVector3D', (['(1.0)', '(0.0)', '(0.0)'], {}), '(1.0, 0.0, 0.0)\n', (2863, 2878), False, 'from PySide2.QtGui import QVector3D\n'), ((3013, 3037), 'PySide2.QtGui.QVector3D', 'QVector3D', (['(1.0)', '(0.0)', '(0.0)'], {}), '(1.0, 0.0, 0.0)\n', (3022, 3037), False, 'from PySide2.QtGui import QVector3D\n'), ((3695, 3719), 'PySide2.QtGui.QVector3D', 'QVector3D', (['(1.0)', '(0.0)', '(0.0)'], {}), '(1.0, 0.0, 0.0)\n', (3704, 3719), False, 'from PySide2.QtGui import QVector3D\n'), ((3854, 3878), 'PySide2.QtGui.QVector3D', 'QVector3D', (['(1.0)', '(0.0)', '(0.0)'], {}), '(1.0, 0.0, 0.0)\n', (3863, 3878), False, 'from PySide2.QtGui import QVector3D\n'), ((4038, 4062), 'PySide2.QtGui.QVector3D', 'QVector3D', (['(1.0)', '(0.0)', '(0.0)'], {}), '(1.0, 0.0, 0.0)\n', (4047, 4062), False, 'from PySide2.QtGui import QVector3D\n')]