from django.views.generic.base import View

from mock import MagicMock

from corehq.apps.reports.dispatcher import ReportDispatcher
from corehq.apps.reports.generic import GenericReportView

from ..permissions import is_location_safe, location_safe


@location_safe
def safe_fn_view(request, domain):
    return "hello"


def unsafe_fn_view(request, domain):
    return "hello"


@location_safe
class SafeClsView(View):
    pass


class UnsafeClsView(View):
    pass


class UnSafeChildOfSafeClsView(SafeClsView):
    """This inherits its parent class's safety"""  # TODO change this behavior


@location_safe
class SafeChildofUnsafeClsView(UnsafeClsView):
    """This shouldn't hoist its safety up to the parent class"""


def test_django_view_safety():
    def _assert(view_fn, is_safe):
        assert is_location_safe(view_fn, MagicMock(), (), {}) == is_safe, \
            f"{view_fn} {'IS NOT' if is_safe else 'IS'} marked as location-safe"

    for view, is_safe in [
            (safe_fn_view, True),
            (unsafe_fn_view, False),
            (SafeClsView.as_view(), True),
            (UnsafeClsView.as_view(), False),
            (UnSafeChildOfSafeClsView.as_view(), True),
            (SafeChildofUnsafeClsView.as_view(), True),
    ]:
        yield _assert, view, is_safe


class ExampleReportDispatcher(ReportDispatcher):
    @classmethod
    def get_reports(cls, domain):
        return [('All Reports', [r for r, is_safe in EXAMPLE_REPORTS])]


class BaseReport(GenericReportView):
    dispatcher = ExampleReportDispatcher


@location_safe
class SafeHQReport(BaseReport):
    slug = 'safe_hq_report'


class UnsafeHQReport(BaseReport):
    slug = 'unsafe_hq_report'


class UnsafeChildOfSafeHQReport(SafeHQReport):
    slug = 'unsafe_child_of_safe_hq_report'


@location_safe
class SafeChildOfUnsafeHQReport(UnsafeHQReport):
    slug = 'safe_child_of_unsafe_hq_report'


EXAMPLE_REPORTS = [
    (SafeHQReport, True),
    (UnsafeHQReport, False),
    (UnsafeChildOfSafeHQReport, False),
    (SafeChildOfUnsafeHQReport, True),
]


def test_hq_report_safety():
    for report, is_safe in EXAMPLE_REPORTS:
        def _assert(report, is_safe):
            view_fn = report.dispatcher.as_view()
            view_kwargs = {'domain': 'foo', 'report_slug': report.slug}
            assert is_location_safe(view_fn, MagicMock(), (), view_kwargs) == is_safe, \
                f"{report} {'IS NOT' if is_safe else 'IS'} marked as location-safe"

        yield _assert, report, is_safe

@@ -209,16 +209,45 @@
 s import
+ conditionally_location_safe,
  is_loca
@@ -1315,16 +1315,873 @@
 _safe%0A%0A%0A
+def _sometimes_safe(view_fn, request, *args, **kwargs):%0A    return request.this_is_safe%0A%0A%0A@conditionally_location_safe(_sometimes_safe)%0Adef conditionally_safe_fn_view(request, domain):%0A    return %22hello%22%0A%0A%0A@conditionally_location_safe(_sometimes_safe)%0Aclass ConditionallySafeClsView(View):%0A    pass%0A%0A%0Adef test_conditionally_safe_django_views():%0A    safe_request = MagicMock(this_is_safe=True)%0A    unsafe_request = MagicMock(this_is_safe=False)%0A    def _assert(view_fn, request, is_safe):%0A        assert is_location_safe(view_fn, request, (), %7B%7D) == is_safe, %5C%0A            f%22%7Bview_fn%7D %7B'IS NOT' if is_safe else 'IS'%7D marked as location-safe%22%0A%0A    for view in %5B%0A            conditionally_safe_fn_view,%0A            ConditionallySafeClsView.as_view(),%0A    %5D:%0A        yield _assert, view, safe_request, True%0A        yield _assert, view, unsafe_request, False%0A%0A%0A%0A
 class Ex

Test conditionally safe views