#!/usr/bin/env python

"""Tests return widget types"""

import pathlib
from contextlib import suppress
from datetime import date, datetime, time
from inspect import signature

import pytest

import magicgui
from magicgui import widgets


def _default_equals(object1, object2):
    assert object1 == object2


def _generate_pandas_test_data():
    pd = pytest.importorskip(
        "pandas", reason="Pandas required for a return widget test"
    )
    return pd.DataFrame({"Res1": [1, 2, 3], "Res2": [4, 5, 6]})


parameterizations = [
    # NOTE: disabling for now... these types are too broad to choose a table
    # # dict
    # ({"a": [1], "b": [2], "c": [3]}, widgets.Table, _default_equals),
    # # list
    # ([1, 2, 3], widgets.Table, _default_equals),
    # # tuple
    # (([[1], [2], [3]], ["A", "B", "C"], ["Row 1"]), widgets.Table, _default_equals),
    # boolean
    (True, widgets.LineEdit, _default_equals),
    # int
    (5, widgets.LineEdit, _default_equals),
    # float
    (3.5, widgets.LineEdit, _default_equals),
    # string
    ("foo", widgets.LineEdit, _default_equals),
    # path
    (pathlib.Path().absolute(), widgets.LineEdit, _default_equals),
    # date
    (date.today(), widgets.LineEdit, _default_equals),
    # time
    (time(), widgets.LineEdit, _default_equals),
    # datetime
    (datetime.now(), widgets.LineEdit, _default_equals),
    # range
    (range(10), widgets.LineEdit, _default_equals),
    # slice
    (slice(6), widgets.LineEdit, _default_equals),
]

with suppress(ImportError):
    import numpy as np

    def _ndarray_equals(object1: np.ndarray, object2: np.ndarray):
        assert np.array_equal(object1, object2)

    parameterizations.append(
        (
            np.array([1, 1, 1, 2, 2, 2, 3, 3, 3]).reshape((3, 3)),
            widgets.Table,
            _ndarray_equals,
        )
    )

with suppress(ImportError):

    def _dataframe_equals(object1, object2):
        assert object1.equals(object2)

    parameterizations.append(
        (
            _generate_pandas_test_data(),
            widgets.Table,
            _dataframe_equals,
        )
    )


def generate_magicgui(data):
    def func():
        return data

    sig = signature(func)
    func.__signature__ = sig.replace(return_annotation=type(data))

    return magicgui.magicgui(func, result_widget=True)


@pytest.mark.parametrize("data, expected_type, equality_check", parameterizations)
def test_return_widget_for_type(data, expected_type, equality_check):
    widget = generate_magicgui(data)
    equality_check(widget(), data)
    assert isinstance(widget._result_widget, expected_type)


def test_table_return_annotation():
    @magicgui.magicgui(result_widget=True)
    def f() -> "magicgui.widgets.Table": ...

    @magicgui.magicgui(result_widget=True)
    def f2() -> widgets.Table: ...

    assert isinstance(f._result_widget, widgets.Table)
    assert isinstance(f2._result_widget, widgets.Table)
