from datetime import date, datetime

from django.conf.urls.i18n import i18n_patterns
from django.contrib.sitemaps import GenericSitemap, Sitemap, views
from django.http import HttpResponse
from django.urls import path
from django.utils import timezone
from django.views.decorators.cache import cache_page

from ..models import I18nTestModel, TestModel


class SimpleSitemap(Sitemap):
    changefreq = "never"
    priority = 0.5
    location = "/location/"
    lastmod = date.today()

    def items(self):
        return [object()]


class SimplePagedSitemap(Sitemap):
    lastmod = date.today()

    def items(self):
        return [object() for x in range(Sitemap.limit + 1)]


class SimpleI18nSitemap(Sitemap):
    changefreq = "never"
    priority = 0.5
    i18n = True

    def items(self):
        return I18nTestModel.objects.order_by("pk").all()


class AlternatesI18nSitemap(SimpleI18nSitemap):
    alternates = True


class LimitedI18nSitemap(AlternatesI18nSitemap):
    languages = ["en", "es"]


class XDefaultI18nSitemap(AlternatesI18nSitemap):
    x_default = True


class ItemByLangSitemap(SimpleI18nSitemap):
    def get_languages_for_item(self, item):
        if item.name == "Only for PT":
            return ["pt"]
        return super().get_languages_for_item(item)


class ItemByLangAlternatesSitemap(AlternatesI18nSitemap):
    x_default = True

    def get_languages_for_item(self, item):
        if item.name == "Only for PT":
            return ["pt"]
        return super().get_languages_for_item(item)


class EmptySitemap(Sitemap):
    changefreq = "never"
    priority = 0.5
    location = "/location/"


class FixedLastmodSitemap(SimpleSitemap):
    lastmod = datetime(2013, 3, 13, 10, 0, 0)


class FixedLastmodMixedSitemap(Sitemap):
    changefreq = "never"
    priority = 0.5
    location = "/location/"
    loop = 0

    def items(self):
        o1 = TestModel()
        o1.lastmod = datetime(2013, 3, 13, 10, 0, 0)
        o2 = TestModel()
        return [o1, o2]


class FixedNewerLastmodSitemap(SimpleSitemap):
    lastmod = datetime(2013, 4, 20, 5, 0, 0)


class DateSiteMap(SimpleSitemap):
    lastmod = date(2013, 3, 13)


class TimezoneSiteMap(SimpleSitemap):
    lastmod = datetime(2013, 3, 13, 10, 0, 0, tzinfo=timezone.get_fixed_timezone(-300))


class CallableLastmodPartialSitemap(Sitemap):
    """Not all items have `lastmod`."""

    location = "/location/"

    def items(self):
        o1 = TestModel()
        o1.lastmod = datetime(2013, 3, 13, 10, 0, 0)
        o2 = TestModel()
        return [o1, o2]

    def lastmod(self, obj):
        return obj.lastmod


class CallableLastmodFullSitemap(Sitemap):
    """All items have `lastmod`."""

    location = "/location/"

    def items(self):
        o1 = TestModel()
        o1.lastmod = datetime(2013, 3, 13, 10, 0, 0)
        o2 = TestModel()
        o2.lastmod = datetime(2014, 3, 13, 10, 0, 0)
        return [o1, o2]

    def lastmod(self, obj):
        return obj.lastmod


class CallableLastmodNoItemsSitemap(Sitemap):
    location = "/location/"

    def items(self):
        return []

    def lastmod(self, obj):
        return obj.lastmod


class GetLatestLastmodNoneSiteMap(Sitemap):
    changefreq = "never"
    priority = 0.5
    location = "/location/"

    def items(self):
        return [object()]

    def lastmod(self, obj):
        return datetime(2013, 3, 13, 10, 0, 0)

    def get_latest_lastmod(self):
        return None


class GetLatestLastmodSiteMap(SimpleSitemap):
    def get_latest_lastmod(self):
        return datetime(2013, 3, 13, 10, 0, 0)


def testmodelview(request, id):
    return HttpResponse()


simple_sitemaps = {
    "simple": SimpleSitemap,
}

simple_i18n_sitemaps = {
    "i18n": SimpleI18nSitemap,
}

alternates_i18n_sitemaps = {
    "i18n-alternates": AlternatesI18nSitemap,
}

limited_i18n_sitemaps = {
    "i18n-limited": LimitedI18nSitemap,
}

xdefault_i18n_sitemaps = {
    "i18n-xdefault": XDefaultI18nSitemap,
}

item_by_lang_i18n_sitemaps = {
    "i18n-item-by-lang": ItemByLangSitemap,
}

item_by_lang_alternates_i18n_sitemaps = {
    "i18n-item-by-lang-alternates": ItemByLangAlternatesSitemap,
}

simple_sitemaps_not_callable = {
    "simple": SimpleSitemap(),
}

simple_sitemaps_paged = {
    "simple": SimplePagedSitemap,
}

empty_sitemaps = {
    "empty": EmptySitemap,
}

fixed_lastmod_sitemaps = {
    "fixed-lastmod": FixedLastmodSitemap,
}

fixed_lastmod_mixed_sitemaps = {
    "fixed-lastmod-mixed": FixedLastmodMixedSitemap,
}

sitemaps_lastmod_mixed_ascending = {
    "no-lastmod": EmptySitemap,
    "lastmod": FixedLastmodSitemap,
}

sitemaps_lastmod_mixed_descending = {
    "lastmod": FixedLastmodSitemap,
    "no-lastmod": EmptySitemap,
}

sitemaps_lastmod_ascending = {
    "date": DateSiteMap,
    "datetime": FixedLastmodSitemap,
    "datetime-newer": FixedNewerLastmodSitemap,
}

sitemaps_lastmod_descending = {
    "datetime-newer": FixedNewerLastmodSitemap,
    "datetime": FixedLastmodSitemap,
    "date": DateSiteMap,
}

generic_sitemaps = {
    "generic": GenericSitemap({"queryset": TestModel.objects.order_by("pk").all()}),
}

get_latest_lastmod_none_sitemaps = {
    "get-latest-lastmod-none": GetLatestLastmodNoneSiteMap,
}

get_latest_lastmod_sitemaps = {
    "get-latest-lastmod": GetLatestLastmodSiteMap,
}

latest_lastmod_timezone_sitemaps = {
    "latest-lastmod-timezone": TimezoneSiteMap,
}

generic_sitemaps_lastmod = {
    "generic": GenericSitemap(
        {
            "queryset": TestModel.objects.order_by("pk").all(),
            "date_field": "lastmod",
        }
    ),
}

callable_lastmod_partial_sitemap = {
    "callable-lastmod": CallableLastmodPartialSitemap,
}

callable_lastmod_full_sitemap = {
    "callable-lastmod": CallableLastmodFullSitemap,
}

callable_lastmod_no_items_sitemap = {
    "callable-lastmod": CallableLastmodNoItemsSitemap,
}

urlpatterns = [
    path("simple/index.xml", views.index, {"sitemaps": simple_sitemaps}),
    path("simple-paged/index.xml", views.index, {"sitemaps": simple_sitemaps_paged}),
    path(
        "simple-not-callable/index.xml",
        views.index,
        {"sitemaps": simple_sitemaps_not_callable},
    ),
    path(
        "simple/custom-index.xml",
        views.index,
        {"sitemaps": simple_sitemaps, "template_name": "custom_sitemap_index.xml"},
    ),
    path(
        "simple/custom-lastmod-index.xml",
        views.index,
        {
            "sitemaps": simple_sitemaps,
            "template_name": "custom_sitemap_lastmod_index.xml",
        },
    ),
    path(
        "simple/sitemap-<section>.xml",
        views.sitemap,
        {"sitemaps": simple_sitemaps},
        name="django.contrib.sitemaps.views.sitemap",
    ),
    path(
        "simple/sitemap.xml",
        views.sitemap,
        {"sitemaps": simple_sitemaps},
        name="django.contrib.sitemaps.views.sitemap",
    ),
    path(
        "simple/i18n.xml",
        views.sitemap,
        {"sitemaps": simple_i18n_sitemaps},
        name="django.contrib.sitemaps.views.sitemap",
    ),
    path(
        "alternates/i18n.xml",
        views.sitemap,
        {"sitemaps": alternates_i18n_sitemaps},
        name="django.contrib.sitemaps.views.sitemap",
    ),
    path(
        "limited/i18n.xml",
        views.sitemap,
        {"sitemaps": limited_i18n_sitemaps},
        name="django.contrib.sitemaps.views.sitemap",
    ),
    path(
        "x-default/i18n.xml",
        views.sitemap,
        {"sitemaps": xdefault_i18n_sitemaps},
        name="django.contrib.sitemaps.views.sitemap",
    ),
    path(
        "simple/custom-sitemap.xml",
        views.sitemap,
        {"sitemaps": simple_sitemaps, "template_name": "custom_sitemap.xml"},
        name="django.contrib.sitemaps.views.sitemap",
    ),
    path(
        "empty/sitemap.xml",
        views.sitemap,
        {"sitemaps": empty_sitemaps},
        name="django.contrib.sitemaps.views.sitemap",
    ),
    path(
        "lastmod/sitemap.xml",
        views.sitemap,
        {"sitemaps": fixed_lastmod_sitemaps},
        name="django.contrib.sitemaps.views.sitemap",
    ),
    path(
        "lastmod-mixed/sitemap.xml",
        views.sitemap,
        {"sitemaps": fixed_lastmod_mixed_sitemaps},
        name="django.contrib.sitemaps.views.sitemap",
    ),
    path(
        "lastmod/date-sitemap.xml",
        views.sitemap,
        {"sitemaps": {"date-sitemap": DateSiteMap}},
        name="django.contrib.sitemaps.views.sitemap",
    ),
    path(
        "lastmod/tz-sitemap.xml",
        views.sitemap,
        {"sitemaps": {"tz-sitemap": TimezoneSiteMap}},
        name="django.contrib.sitemaps.views.sitemap",
    ),
    path(
        "lastmod-sitemaps/mixed-ascending.xml",
        views.sitemap,
        {"sitemaps": sitemaps_lastmod_mixed_ascending},
        name="django.contrib.sitemaps.views.sitemap",
    ),
    path(
        "lastmod-sitemaps/mixed-descending.xml",
        views.sitemap,
        {"sitemaps": sitemaps_lastmod_mixed_descending},
        name="django.contrib.sitemaps.views.sitemap",
    ),
    path(
        "lastmod-sitemaps/ascending.xml",
        views.sitemap,
        {"sitemaps": sitemaps_lastmod_ascending},
        name="django.contrib.sitemaps.views.sitemap",
    ),
    path(
        "item-by-lang/i18n.xml",
        views.sitemap,
        {"sitemaps": item_by_lang_i18n_sitemaps},
        name="django.contrib.sitemaps.views.sitemap",
    ),
    path(
        "item-by-lang-alternates/i18n.xml",
        views.sitemap,
        {"sitemaps": item_by_lang_alternates_i18n_sitemaps},
        name="django.contrib.sitemaps.views.sitemap",
    ),
    path(
        "lastmod-sitemaps/descending.xml",
        views.sitemap,
        {"sitemaps": sitemaps_lastmod_descending},
        name="django.contrib.sitemaps.views.sitemap",
    ),
    path(
        "lastmod/get-latest-lastmod-none-sitemap.xml",
        views.index,
        {"sitemaps": get_latest_lastmod_none_sitemaps},
        name="django.contrib.sitemaps.views.index",
    ),
    path(
        "lastmod/get-latest-lastmod-sitemap.xml",
        views.index,
        {"sitemaps": get_latest_lastmod_sitemaps},
        name="django.contrib.sitemaps.views.index",
    ),
    path(
        "lastmod/latest-lastmod-timezone-sitemap.xml",
        views.index,
        {"sitemaps": latest_lastmod_timezone_sitemaps},
        name="django.contrib.sitemaps.views.index",
    ),
    path(
        "generic/sitemap.xml",
        views.sitemap,
        {"sitemaps": generic_sitemaps},
        name="django.contrib.sitemaps.views.sitemap",
    ),
    path(
        "generic-lastmod/sitemap.xml",
        views.sitemap,
        {"sitemaps": generic_sitemaps_lastmod},
        name="django.contrib.sitemaps.views.sitemap",
    ),
    path(
        "cached/index.xml",
        cache_page(1)(views.index),
        {"sitemaps": simple_sitemaps, "sitemap_url_name": "cached_sitemap"},
    ),
    path(
        "cached/sitemap-<section>.xml",
        cache_page(1)(views.sitemap),
        {"sitemaps": simple_sitemaps},
        name="cached_sitemap",
    ),
    path(
        "sitemap-without-entries/sitemap.xml",
        views.sitemap,
        {"sitemaps": {}},
        name="django.contrib.sitemaps.views.sitemap",
    ),
    path(
        "callable-lastmod-partial/index.xml",
        views.index,
        {"sitemaps": callable_lastmod_partial_sitemap},
    ),
    path(
        "callable-lastmod-partial/sitemap.xml",
        views.sitemap,
        {"sitemaps": callable_lastmod_partial_sitemap},
    ),
    path(
        "callable-lastmod-full/index.xml",
        views.index,
        {"sitemaps": callable_lastmod_full_sitemap},
    ),
    path(
        "callable-lastmod-full/sitemap.xml",
        views.sitemap,
        {"sitemaps": callable_lastmod_full_sitemap},
    ),
    path(
        "callable-lastmod-no-items/index.xml",
        views.index,
        {"sitemaps": callable_lastmod_no_items_sitemap},
    ),
    path(
        "generic-lastmod/index.xml",
        views.index,
        {"sitemaps": generic_sitemaps_lastmod},
        name="django.contrib.sitemaps.views.index",
    ),
]

urlpatterns += i18n_patterns(
    path("i18n/testmodel/<int:id>/", testmodelview, name="i18n_testmodel"),
)