import json
import re
from functools import cached_property

from django import forms
from django.conf import settings
from django.core.paginator import Paginator
from django.db import models
from django.db.models.functions import Greatest
from django.http import HttpResponseRedirect
from django.utils.text import slugify
from django.utils.timezone import localtime
from django.utils.translation import gettext_lazy
from modelcluster.contrib.taggit import ClusterTaggableManager
from modelcluster.fields import ParentalKey
from taggit.models import TaggedItemBase
from wagtail import blocks
from wagtail.admin.panels import (
    CommentPanel,
    FieldPanel,
    HelpPanel,
    MultiFieldPanel,
    ObjectList,
    PageChooserPanel,
    PublishingPanel,
    TabbedInterface,
)
from wagtail.blocks import RichTextBlock
from wagtail.contrib.routable_page.models import RoutablePageMixin, route
from wagtail.documents.blocks import DocumentChooserBlock
from wagtail.fields import RichTextField, StreamField
from wagtail.images.blocks import ImageChooserBlock
from wagtail.models import Page
from wagtail.search import index
from wagtailmetadata.models import MetadataPageMixin

from calendar_utils.models import CalendarMixin
from shared.forms import SubscribeForm
from shared.models import SubpageMixin
from shared.models.legacy import ArticleMixin
from shared.utils import get_subpage_url, subscribe_to_newsletter
from tuning import admin_help

from .constants import (
    AGE_30_49,
    ARTICLE_RICH_TEXT_FEATURES,
    ARTICLES_PER_PAGE,
    BENEFITS_CHOICES,
    CANDIDATE_RICH_TEXT_FEATURES,
    CHILDLESS,
    COUNTRYSIDE,
    CULTURE,
    EDUCATION,
    EXTRA_FEATURES,
    HEALTH,
    HOUSING,
    MATURE,
    MINISTRY_AGRICULTURE,
    MINISTRY_ARCHETYPES,
    MINISTRY_BUSINESS,
    MINISTRY_CHOICES,
    MINISTRY_CODES,
    MINISTRY_COUNTRYSIDE,
    MINISTRY_CULTURE,
    MINISTRY_DEFENSE,
    MINISTRY_ENVIRONMENT,
    MINISTRY_FINANCES,
    MINISTRY_FOREIGN,
    MINISTRY_HEALTH,
    MINISTRY_INTERIOR,
    MINISTRY_JUSTICE,
    MINISTRY_OPTIONS,
    MINISTRY_SCHOOLS,
    MINISTRY_SOCIAL,
    MINISTRY_TRANSPORT,
    NATURE,
    OCCUPATION_BUSINESS,
    OCCUPATION_WORKING,
    PARENTS,
    PARTY_CHOICES,
    PARTY_NAME,
    PIRATES,
    PLAN_ARCHETYPES,
    PLAN_CARE,
    PLAN_CHOICES,
    PLAN_CLIMATE,
    PLAN_CORRUPTION,
    PLAN_COUNTRYSIDE,
    PLAN_DIGITAL,
    PLAN_ECONOMICS,
    PLAN_MANAGEMENT,
    PLAN_OPTIONS,
    PLAN_SAFE_COUNTRY,
    PROGRAM_POINTS_PER_PAGE,
    REGION_CHOICES,
    REGION_NAME_VARIANT,
    REGION_OPTIONS,
    REGION_SLUGS,
    RESTRICTED_FEATURES,
    SENIORS,
    SPORT,
    STANDARD_FEATURES,
    STRATEGIC_PER_PAGE,
    STRATEGIC_RICH_TEXT_FEATURES,
    STUDENTS,
    STYLE_CHOICES,
    STYLE_CSS,
    TECHNOLOGY,
    TOP_CANDIDATES_NUM,
    WEALTH_AVERAGE,
    WEALTH_BAD,
    WHITE,
    WORKING_SENIORS,
)
from .forms import ProgramAppForm, ProgramPointPageForm
from .utils import get_archetype

NO_SEARCH_IMAGE_USE_PHOTO = (
    "Pokud není zadán <strong>Search image</strong>, použije se <strong>hlavní "
    "fotka</strong> (tab obsah)."
)


class LinkBlock(blocks.StructBlock):
    title = blocks.CharBlock(label="titulek")
    url = blocks.URLBlock(label="odkaz")

    class Meta:
        icon = "link-external"
        label = "odkaz"


class MenuItemBlock(blocks.StructBlock):
    name = blocks.CharBlock(label="název")
    page = blocks.PageChooserBlock(
        label="stránka",
        page_type=[
            "elections2021.Elections2021ArticlesPage",
            "elections2021.Elections2021CandidatesListPage",
            "elections2021.Elections2021CandidatesMapPage",
            "elections2021.Elections2021ProgramPage",
            "elections2021.Elections2021QuestionsPage",
            "elections2021.Elections2021ProgramAppPage",
            "elections2021.Elections2021TextPage",
            "elections2021.Elections2021StrategicListPage",
            "elections2021.Elections2021StrategicPage",
            "elections2021.Elections2021MythsPage",
            "elections2021.Elections2021DownloadsPage",
            "elections2021.Elections2021GovernmentTeamPage",
            "elections2021.Elections2021CalendarPage",
            "elections2021.Elections2021ProgramInNutshellPage",
            "elections2021.Elections2021GoingToVotePage",
        ],
    )

    class Meta:
        label = "stránka"


class SlideBlock(blocks.StructBlock):
    title = blocks.CharBlock(label="titulek")
    photo = ImageChooserBlock(label="fotka")
    button_label = blocks.CharBlock(label="text tlačítka")
    page = blocks.PageChooserBlock(
        label="stránka do tlačítka",
        page_type=[
            "elections2021.Elections2021ArticlesPage",
            "elections2021.Elections2021CandidatesListPage",
            "elections2021.Elections2021CandidatesMapPage",
            "elections2021.Elections2021ProgramPage",
            "elections2021.Elections2021QuestionsPage",
            "elections2021.Elections2021ProgramAppPage",
            "elections2021.Elections2021TextPage",
            "elections2021.Elections2021StrategicListPage",
            "elections2021.Elections2021StrategicPage",
            "elections2021.Elections2021MythsPage",
            "elections2021.Elections2021DownloadsPage",
            "elections2021.Elections2021GovernmentTeamPage",
            "elections2021.Elections2021CalendarPage",
        ],
        required=False,
    )
    raw_url = blocks.CharBlock(
        label="ručně zadaný odkaz do tlačítka (místo stránky)", required=False
    )

    class Meta:
        label = "slide"
        icon = "media"
        template = "elections2021/_carousel_slide.html"


class Elections2021HomePage(MetadataPageMixin, RoutablePageMixin, Page):
    ### FIELDS

    carousel = StreamField(
        [("slide", SlideBlock())],
        verbose_name="obsah slideru",
        blank=True,
        use_json_field=True,
    )
    elections_date = models.DateTimeField("datum začátku voleb", blank=True, null=True)
    header_links = StreamField(
        [("link", LinkBlock())],
        verbose_name="odkazy v záhlaví",
        blank=True,
        use_json_field=True,
    )
    footer_links = StreamField(
        [("link", LinkBlock())],
        verbose_name="odkazy v zápatí",
        blank=True,
        use_json_field=True,
    )
    footer_menu = StreamField(
        [("item", MenuItemBlock())],
        verbose_name="menu projděte si v zápatí",
        blank=True,
        use_json_field=True,
    )
    gdpr_and_cookies_page = models.ForeignKey(
        "main.MainSimplePage",
        verbose_name="Stránka GDPR a Cookies",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )
    program_strategic_page = models.ForeignKey(
        "wagtailcore.Page",
        verbose_name="stránka program v kostce",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )
    program_silver_page = models.ForeignKey(
        "wagtailcore.Page",
        verbose_name="stránka stříbrný program",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )
    program_for_business = models.ForeignKey(
        "wagtailcore.Page",
        verbose_name="stránka program pro podnikatele",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )
    post_election_strategy = models.ForeignKey(
        "wagtailcore.Page",
        verbose_name="stránka povolební strategie",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )
    matomo_id = models.IntegerField(
        "Matomo ID pro sledování návštěvnosti", blank=True, null=True
    )
    donate_page = models.ForeignKey(
        "wagtailcore.Page",
        verbose_name="stránka darovacího projektu",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )
    onboarding_url = models.URLField(
        "URL registrace dobrovolníků", null=True, blank=True
    )

    ### PANELS

    content_panels = Page.content_panels + [
        FieldPanel("carousel"),
        FieldPanel("elections_date"),
    ]

    header_panels = [
        FieldPanel("header_links"),
        PageChooserPanel(
            "program_strategic_page",
            [
                "elections2021.Elections2021StrategicPage",
                "elections2021.Elections2021ProgramInNutshellPage",
            ],
        ),
        PageChooserPanel(
            "program_silver_page", "elections2021.Elections2021StrategicPage"
        ),
        PageChooserPanel(
            "program_for_business", "elections2021.Elections2021StrategicPage"
        ),
        PageChooserPanel(
            "post_election_strategy", "elections2021.Elections2021StrategicPage"
        ),
    ]

    footer_panels = [
        FieldPanel("footer_menu"),
        FieldPanel("footer_links"),
        PageChooserPanel("gdpr_and_cookies_page", "main.MainSimplePage"),
    ]

    promote_panels = [
        MultiFieldPanel(
            [
                FieldPanel("seo_title"),
                FieldPanel("search_description"),
                FieldPanel("search_image"),
                HelpPanel(admin_help.build(admin_help.IMPORTANT_TITLE)),
            ],
            gettext_lazy("Common page configuration"),
        ),
    ]

    settings_panels = [
        FieldPanel("matomo_id"),
        PageChooserPanel("donate_page", "donate.DonateProjectPage"),
        FieldPanel("onboarding_url"),
        CommentPanel(),
    ]

    edit_handler = TabbedInterface(
        [
            ObjectList(content_panels, heading=gettext_lazy("Content")),
            ObjectList(promote_panels, heading=gettext_lazy("Promote")),
            ObjectList(header_panels, heading="hlavička"),
            ObjectList(footer_panels, heading="patička"),
            ObjectList(
                settings_panels, heading=gettext_lazy("Settings"), classname="settings"
            ),
        ]
    )

    ### RELATIONS

    subpage_types = [
        "elections2021.Elections2021ArticlesPage",
        "elections2021.Elections2021CandidatesListPage",
        "elections2021.Elections2021CandidatesMapPage",
        "elections2021.Elections2021ProgramPage",
        "elections2021.Elections2021QuestionsPage",
        "elections2021.Elections2021ProgramAppPage",
        "elections2021.Elections2021TextPage",
        "elections2021.Elections2021StrategicListPage",
        "elections2021.Elections2021MythsPage",
        "elections2021.Elections2021DownloadsPage",
        "elections2021.Elections2021GovernmentTeamPage",
        "elections2021.Elections2021CalendarPage",
        "elections2021.Elections2021MapPage",
        "elections2021.Elections2021ProgramInNutshellPage",
        "elections2021.Elections2021GoingToVotePage",
    ]

    ### OTHERS

    class Meta:
        verbose_name = "Koaliční web 2021"

    @property
    def root_page(self):
        return self

    @cached_property
    def articles_page_url(self):
        return get_subpage_url(self, Elections2021ArticlesPage)

    @cached_property
    def candidates_list_page_url(self):
        try:
            return (
                self.get_descendants()
                .type(Elections2021CandidatesListPage)
                .live()
                .specific()
                .first()
                .get_region_list_url()
            )
        except (Page.DoesNotExist, AttributeError):
            return "#"

    @cached_property
    def candidates_map_page_url(self):
        return get_subpage_url(self, Elections2021CandidatesMapPage)

    @cached_property
    def questions_page_url(self):
        return get_subpage_url(self, Elections2021QuestionsPage)

    @cached_property
    def program_page_url(self):
        return get_subpage_url(self, Elections2021ProgramPage)

    @cached_property
    def program_app_page_url(self):
        return get_subpage_url(self, Elections2021ProgramAppPage)

    @cached_property
    def strategic_list_page_url(self):
        return get_subpage_url(self, Elections2021StrategicListPage)

    @cached_property
    def downloads_page_url(self):
        return get_subpage_url(self, Elections2021DownloadsPage)

    @cached_property
    def myths_page_url(self):
        return get_subpage_url(self, Elections2021MythsPage)

    @cached_property
    def government_team_page_url(self):
        return get_subpage_url(self, Elections2021GovernmentTeamPage)

    @cached_property
    def going_to_vote_page_url(self):
        return get_subpage_url(self, Elections2021GoingToVotePage)

    @cached_property
    def full_program_page_url(self):
        try:
            return (
                self.get_descendants()
                .type(Elections2021ProgramPage)
                .live()
                .specific()
                .first()
                .get_full_program_url()
            )
        except (Page.DoesNotExist, AttributeError):
            return "#"

    @cached_property
    def has_calendar(self):
        try:
            self.calendar
            return True
        except (Page.DoesNotExist, AttributeError):
            return False

    @cached_property
    def calendar_page_url(self):
        return get_subpage_url(self, Elections2021CalendarPage)

    @cached_property
    def calendar(self):
        return (
            self.get_descendants()
            .type(Elections2021CalendarPage)
            .live()
            .specific()
            .first()
            .get_calendar()
        )

    @cached_property
    def gdpr_and_cookies_url(self):
        if self.gdpr_and_cookies_page:
            return self.gdpr_and_cookies_page.url
        return "#"

    @cached_property
    def program_strategic_page_url(self):
        if self.program_strategic_page:
            return self.program_strategic_page.url
        return "#"

    @cached_property
    def program_silver_page_url(self):
        if self.program_silver_page:
            return self.program_silver_page.url
        return "#"

    @cached_property
    def program_for_business_url(self):
        if self.program_for_business:
            return self.program_for_business.url
        return "#"

    @cached_property
    def post_election_strategy_url(self):
        if self.post_election_strategy:
            return self.post_election_strategy.url
        return "#"

    @cached_property
    def newsletter_subscribe_url(self):
        return self.url + self.reverse_subpage("newsletter_subscribe")

    def get_context(self, request):
        context = super().get_context(request)
        context["articles"] = (
            Elections2021ArticlePage.objects.live()
            .specific()
            .order_by("-timestamp")[:3]
        )
        context["questions"] = (
            Elections2021QuestionsPage.objects.live().specific().first().elections[:3]
        )
        if self.elections_date:
            delta = self.elections_date - localtime()
            if delta.total_seconds() < 0:
                context["countdown_days"] = 0
                context["countdown_hours"] = 0
            else:
                days, reminder = divmod(delta.total_seconds(), 60 * 60 * 24)
                hours, reminder = divmod(reminder, 60 * 60)
                context["countdown_days"] = int(days)
                context["countdown_hours"] = int(hours)
        return context

    @route(r"^prihlaseni-k-newsletteru/$")
    def newsletter_subscribe(self, request):
        if request.method == "POST":
            form = SubscribeForm(request.POST)
            if form.is_valid():
                subscribe_to_newsletter(
                    form.cleaned_data["email"], settings.ELECTIONS2021_NEWSLETTER_CID
                )
                try:
                    page = (
                        Page.objects.filter(id=form.cleaned_data["return_page_id"])
                        .live()
                        .first()
                    )
                    return HttpResponseRedirect(page.full_url)
                except Page.DoesNotExist:
                    return HttpResponseRedirect(self.url)
        return HttpResponseRedirect(self.url)


class Elections2021ArticleTag(TaggedItemBase):
    content_object = ParentalKey(
        "elections2021.Elections2021ArticlePage",
        on_delete=models.CASCADE,
        related_name="tagged_items",
    )


class Elections2021ArticlePage(ArticleMixin, SubpageMixin, MetadataPageMixin, Page):
    ### FIELDS

    content = StreamField(
        [
            (
                "text",
                RichTextBlock(
                    label="Textový editor", features=ARTICLE_RICH_TEXT_FEATURES
                ),
            )
        ],
        verbose_name="Článek",
        blank=True,
        use_json_field=True,
    )
    tags = ClusterTaggableManager(through=Elections2021ArticleTag, blank=True)
    card_style = models.CharField(
        "styl karty článku", choices=STYLE_CHOICES, default=WHITE, max_length=10
    )

    ### PANELS

    content_panels = ArticleMixin.content_panels + [
        FieldPanel("tags"),
        FieldPanel("card_style"),
    ]

    promote_panels = [
        MultiFieldPanel(
            [
                FieldPanel("slug"),
                FieldPanel("seo_title"),
                FieldPanel("search_description"),
                HelpPanel(
                    admin_help.build(
                        admin_help.NO_SEO_TITLE, admin_help.NO_DESCRIPTION_USE_PEREX
                    )
                ),
            ],
            gettext_lazy("Common page configuration"),
        ),
    ]

    settings_panels = [PublishingPanel(), CommentPanel()]

    ### RELATIONS

    parent_page_types = ["elections2021.Elections2021ArticlesPage"]
    subpage_types = []

    ### OTHERS

    class Meta:
        verbose_name = "Aktualita"

    def card_css_class(self):
        return STYLE_CSS[self.card_style]

    def get_context(self, request):
        context = super().get_context(request)
        context["related_articles"] = (
            self.get_siblings(inclusive=False)
            .live()
            .specific()
            .order_by("-elections2021articlepage__timestamp")[:3]
        )
        return context


class Elections2021ArticlesPage(SubpageMixin, MetadataPageMixin, Page):
    ### FIELDS

    photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="hlavní fotka",
    )

    ### PANELS

    content_panels = Page.content_panels + [FieldPanel("photo")]

    promote_panels = [
        MultiFieldPanel(
            [
                FieldPanel("slug"),
                FieldPanel("seo_title"),
                FieldPanel("search_description"),
                FieldPanel("search_image"),
                HelpPanel(
                    admin_help.build(admin_help.NO_SEO_TITLE, NO_SEARCH_IMAGE_USE_PHOTO)
                ),
            ],
            gettext_lazy("Common page configuration"),
        ),
        CommentPanel(),
    ]

    settings_panels = []

    ### RELATIONS

    parent_page_types = ["elections2021.Elections2021HomePage"]
    subpage_types = ["elections2021.Elections2021ArticlePage"]

    ### OTHERS

    class Meta:
        verbose_name = "Aktuality"

    def get_meta_image(self):
        return self.search_image or self.photo

    def get_context(self, request):
        context = super().get_context(request)
        context["articles"] = Paginator(
            self.get_children()
            .live()
            .specific()
            .order_by("-elections2021articlepage__timestamp"),
            ARTICLES_PER_PAGE,
        ).get_page(request.GET.get("page"))
        return context


class Elections2021CandidatesListPage(
    SubpageMixin, MetadataPageMixin, RoutablePageMixin, Page
):
    ### FIELDS

    photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="hlavní fotka",
    )

    ### PANELS

    content_panels = Page.content_panels + [FieldPanel("photo")]

    promote_panels = [
        MultiFieldPanel(
            [
                FieldPanel("slug"),
                FieldPanel("seo_title"),
                FieldPanel("search_description"),
                FieldPanel("search_image"),
                HelpPanel(
                    admin_help.build(admin_help.NO_SEO_TITLE, NO_SEARCH_IMAGE_USE_PHOTO)
                ),
            ],
            gettext_lazy("Common page configuration"),
        ),
        CommentPanel(),
    ]

    settings_panels = []

    ### RELATIONS

    parent_page_types = ["elections2021.Elections2021HomePage"]
    subpage_types = ["elections2021.Elections2021CandidatePage"]

    ### OTHERS

    class Meta:
        verbose_name = "Kandidáti"

    def get_meta_image(self):
        return self.search_image or self.photo

    def get_context(self, request):
        context = super().get_context(request)
        context["region_options"] = REGION_OPTIONS
        return context

    def get_region_list_url(self, slug=None):
        if slug is None:
            slug = list(REGION_SLUGS.keys())[0]
        return self.url + self.reverse_subpage("region_list", args=(slug,))

    @route(r"^$")
    @route(r"^kraj/$")
    @route(r"^kraj/([a-z]+)/$")
    def region_list(self, request, param=None):
        region = param if param in REGION_SLUGS else None
        if not region:
            return HttpResponseRedirect(self.get_region_list_url())

        candidates = (
            self.get_children()
            .filter(elections2021candidatepage__region=REGION_SLUGS[region])
            .live()
            .specific()
            .order_by("elections2021candidatepage__number")
        )

        context = {
            "active_region": region,
            "candidates_top": candidates[:TOP_CANDIDATES_NUM],
            "candidates_bottom": candidates[TOP_CANDIDATES_NUM:],
        }
        return self.render(request, context_overrides=context)


class Elections2021CandidatesMapPage(SubpageMixin, MetadataPageMixin, Page):
    ### FIELDS

    photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="hlavní fotka",
    )

    ### PANELS

    content_panels = Page.content_panels + [FieldPanel("photo")]

    promote_panels = [
        MultiFieldPanel(
            [
                FieldPanel("slug"),
                FieldPanel("seo_title"),
                FieldPanel("search_description"),
                FieldPanel("search_image"),
                HelpPanel(
                    admin_help.build(admin_help.NO_SEO_TITLE, NO_SEARCH_IMAGE_USE_PHOTO)
                ),
            ],
            gettext_lazy("Common page configuration"),
        ),
        CommentPanel(),
    ]

    settings_panels = []

    ### RELATIONS

    parent_page_types = ["elections2021.Elections2021HomePage"]
    subpage_types = []

    ### OTHERS

    class Meta:
        verbose_name = "Kandidáti mapa"

    def get_meta_image(self):
        return self.search_image or self.photo


class Elections2021CandidatePage(SubpageMixin, MetadataPageMixin, Page):
    ### FIELDS

    party = models.CharField(
        "strana", choices=PARTY_CHOICES, default=PIRATES, max_length=6
    )
    region = models.CharField("kraj", choices=REGION_CHOICES, max_length=3)
    number = models.IntegerField("pořadí")
    age = models.IntegerField("věk")
    occupation = models.CharField("povolání", max_length=255)
    city = models.CharField("bydliště", max_length=100)
    resume = RichTextField("medailonek", features=CANDIDATE_RICH_TEXT_FEATURES)
    email = models.EmailField("email", null=True, blank=True)
    phone = models.CharField("telefon", null=True, blank=True, max_length=20)
    facebook_url = models.URLField("Facebook URL", blank=True, null=True)
    twitter_url = models.URLField("Twitter URL", blank=True, null=True)
    instagram_url = models.URLField("Instagram URL", blank=True, null=True)
    website_url = models.URLField("webová stránka", blank=True, null=True)
    photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="foto",
    )

    ### PANELS

    content_panels = Page.content_panels + [
        MultiFieldPanel(
            [
                FieldPanel("party", widget=forms.RadioSelect),
                FieldPanel("region"),
                FieldPanel("number"),
            ],
            "zařazení",
        ),
        MultiFieldPanel(
            [
                FieldPanel("age"),
                FieldPanel("occupation"),
                FieldPanel("city"),
            ],
            "osobní údaje",
        ),
        FieldPanel("photo"),
        FieldPanel("resume"),
        MultiFieldPanel(
            [
                FieldPanel("email"),
                FieldPanel("phone"),
                FieldPanel("facebook_url"),
                FieldPanel("twitter_url"),
                FieldPanel("instagram_url"),
                FieldPanel("website_url"),
            ],
            "kontakty",
        ),
    ]

    promote_panels = [
        MultiFieldPanel(
            [
                FieldPanel("slug"),
            ],
            gettext_lazy("Common page configuration"),
        ),
        CommentPanel(),
    ]

    settings_panels = []

    ### RELATIONS

    parent_page_types = ["elections2021.Elections2021CandidatesListPage"]
    subpage_types = []

    ### OTHERS

    class Meta:
        verbose_name = "Detail kandidáta"

    def get_meta_image(self):
        return self.photo

    def get_meta_description(self):
        name = REGION_NAME_VARIANT[self.region]
        return f"Kandidát č. {self.number} za koalici Piráti a Starostové v {name}."

    @property
    def party_name(self):
        return PARTY_NAME[self.party]

    @property
    def is_pirate(self):
        return self.party == PIRATES

    def get_region_list_url(self):
        slug = next(slug for slug, code in REGION_SLUGS.items() if code == self.region)
        candidates_list = Elections2021CandidatesListPage.objects.live().first()
        return candidates_list.get_region_list_url(slug)


class Elections2021ProgramPage(
    SubpageMixin, MetadataPageMixin, RoutablePageMixin, Page
):
    ### FIELDS

    head_title = models.CharField(
        "nadpis do hlavičky stránky", blank=True, null=True, max_length=255
    )
    photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="hlavní fotka",
    )
    plan_economics_text = RichTextField(
        "Moderní ekonomika", blank=True, null=True, features=RESTRICTED_FEATURES
    )
    plan_digital_text = RichTextField(
        "Digitální revoluce", blank=True, null=True, features=RESTRICTED_FEATURES
    )
    plan_corruption_text = RichTextField(
        "Razantní boj s korupcí", blank=True, null=True, features=RESTRICTED_FEATURES
    )
    plan_climate_text = RichTextField(
        "Důraz na klima", blank=True, null=True, features=RESTRICTED_FEATURES
    )
    plan_countryside_text = RichTextField(
        "Rovnocenné regiony", blank=True, null=True, features=RESTRICTED_FEATURES
    )
    plan_management_text = RichTextField(
        "Profesionální stát", blank=True, null=True, features=RESTRICTED_FEATURES
    )
    plan_safe_country_text = RichTextField(
        "Sebevědomá a bezpečná země",
        blank=True,
        null=True,
        features=RESTRICTED_FEATURES,
    )
    plan_care_text = RichTextField(
        "Jistota péče a pomoci", blank=True, null=True, features=RESTRICTED_FEATURES
    )

    archetype_childless_text = RichTextField(
        "bezdětní text", blank=True, null=True, features=RESTRICTED_FEATURES
    )
    archetype_childless_author_1 = models.CharField(
        "bezdětní podpis 1", null=True, blank=True, max_length=150
    )
    archetype_childless_author_2 = models.CharField(
        "bezdětní podpis 2", null=True, blank=True, max_length=150
    )
    archetype_childless_photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="bezdětní foto",
        related_name="+",
    )
    archetype_parents_text = RichTextField(
        "rodiče text", blank=True, null=True, features=RESTRICTED_FEATURES
    )
    archetype_parents_author_1 = models.CharField(
        "rodiče podpis 1", null=True, blank=True, max_length=150
    )
    archetype_parents_author_2 = models.CharField(
        "rodiče podpis 2", null=True, blank=True, max_length=150
    )
    archetype_parents_photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="rodiče foto",
        related_name="+",
    )
    archetype_mature_text = RichTextField(
        "zralí text", blank=True, null=True, features=RESTRICTED_FEATURES
    )
    archetype_mature_author_1 = models.CharField(
        "zralí podpis 1", null=True, blank=True, max_length=150
    )
    archetype_mature_author_2 = models.CharField(
        "zralí podpis 2", null=True, blank=True, max_length=150
    )
    archetype_mature_photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="zralí foto",
        related_name="+",
    )
    archetype_seniors_text = RichTextField(
        "senioři text", blank=True, null=True, features=RESTRICTED_FEATURES
    )
    archetype_seniors_author_1 = models.CharField(
        "senioři podpis 1", null=True, blank=True, max_length=150
    )
    archetype_seniors_author_2 = models.CharField(
        "senioři podpis 2", null=True, blank=True, max_length=150
    )
    archetype_seniors_photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="senioři foto",
        related_name="+",
    )
    archetype_working_seniors_text = RichTextField(
        "pracující senioři text", blank=True, null=True, features=RESTRICTED_FEATURES
    )
    archetype_working_seniors_author_1 = models.CharField(
        "pracující senioři podpis 1", null=True, blank=True, max_length=150
    )
    archetype_working_seniors_author_2 = models.CharField(
        "pracující senioři podpis 2", null=True, blank=True, max_length=150
    )
    archetype_working_seniors_photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="pracující senioři foto",
        related_name="+",
    )
    archetype_students_text = RichTextField(
        "studenti text", blank=True, null=True, features=RESTRICTED_FEATURES
    )
    archetype_students_author_1 = models.CharField(
        "studenti podpis 1", null=True, blank=True, max_length=150
    )
    archetype_students_author_2 = models.CharField(
        "studenti podpis 2", null=True, blank=True, max_length=150
    )
    archetype_students_photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="studenti foto",
        related_name="+",
    )

    ministry_transport_photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="doprava foto",
        related_name="+",
    )
    ministry_finances_photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="finance foto",
        related_name="+",
    )
    ministry_culture_photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="kultura foto",
        related_name="+",
    )
    ministry_defense_photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="obrana foto",
        related_name="+",
    )
    ministry_social_photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="práce a sociální věci foto",
        related_name="+",
    )
    ministry_countryside_photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="místní rozvoj foto",
        related_name="+",
    )
    ministry_business_photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="průmysl a obchod foto",
        related_name="+",
    )
    ministry_justice_photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="spravedlnost foto",
        related_name="+",
    )
    ministry_schools_photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="školství, mládež a tělovýchova foto",
        related_name="+",
    )
    ministry_interior_photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="vnitro foto",
        related_name="+",
    )
    ministry_foreign_photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="zahraniční věci foto",
        related_name="+",
    )
    ministry_health_photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="zdravotnictví foto",
        related_name="+",
    )
    ministry_agriculture_photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="zemědělství foto",
        related_name="+",
    )
    ministry_environment_photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="životní prostředí foto",
        related_name="+",
    )

    ### PANELS

    content_panels = Page.content_panels + [
        FieldPanel("head_title"),
        FieldPanel("photo"),
    ]

    promote_panels = [
        MultiFieldPanel(
            [
                FieldPanel("slug"),
                FieldPanel("seo_title"),
                FieldPanel("search_description"),
                FieldPanel("search_image"),
                HelpPanel(
                    admin_help.build(admin_help.NO_SEO_TITLE, NO_SEARCH_IMAGE_USE_PHOTO)
                ),
            ],
            gettext_lazy("Common page configuration"),
        ),
        CommentPanel(),
    ]

    plan_panels = [
        FieldPanel("plan_economics_text"),
        FieldPanel("plan_digital_text"),
        FieldPanel("plan_corruption_text"),
        FieldPanel("plan_climate_text"),
        FieldPanel("plan_countryside_text"),
        FieldPanel("plan_management_text"),
        FieldPanel("plan_safe_country_text"),
        FieldPanel("plan_care_text"),
    ]

    archetype_panels = [
        MultiFieldPanel(
            [
                FieldPanel("archetype_childless_text"),
                FieldPanel("archetype_childless_author_1"),
                FieldPanel("archetype_childless_author_2"),
                FieldPanel("archetype_childless_photo"),
            ],
            "archetyp bezdětní",
        ),
        MultiFieldPanel(
            [
                FieldPanel("archetype_parents_text"),
                FieldPanel("archetype_parents_author_1"),
                FieldPanel("archetype_parents_author_2"),
                FieldPanel("archetype_parents_photo"),
            ],
            "archetyp rodiče",
        ),
        MultiFieldPanel(
            [
                FieldPanel("archetype_mature_text"),
                FieldPanel("archetype_mature_author_1"),
                FieldPanel("archetype_mature_author_2"),
                FieldPanel("archetype_mature_photo"),
            ],
            "archetyp zralí",
        ),
        MultiFieldPanel(
            [
                FieldPanel("archetype_seniors_text"),
                FieldPanel("archetype_seniors_author_1"),
                FieldPanel("archetype_seniors_author_2"),
                FieldPanel("archetype_seniors_photo"),
            ],
            "archetyp senioři",
        ),
        MultiFieldPanel(
            [
                FieldPanel("archetype_working_seniors_text"),
                FieldPanel("archetype_working_seniors_author_1"),
                FieldPanel("archetype_working_seniors_author_2"),
                FieldPanel("archetype_working_seniors_photo"),
            ],
            "archetyp pracující senioři",
        ),
        MultiFieldPanel(
            [
                FieldPanel("archetype_students_text"),
                FieldPanel("archetype_students_author_1"),
                FieldPanel("archetype_students_author_2"),
                FieldPanel("archetype_students_photo"),
            ],
            "archetyp studenti",
        ),
    ]

    ministry_panels = [
        FieldPanel("ministry_transport_photo"),
        FieldPanel("ministry_finances_photo"),
        FieldPanel("ministry_culture_photo"),
        # FieldPanel("ministry_defense_photo"),
        FieldPanel("ministry_social_photo"),
        FieldPanel("ministry_countryside_photo"),
        FieldPanel("ministry_business_photo"),
        FieldPanel("ministry_justice_photo"),
        FieldPanel("ministry_schools_photo"),
        FieldPanel("ministry_interior_photo"),
        FieldPanel("ministry_foreign_photo"),
        FieldPanel("ministry_health_photo"),
        FieldPanel("ministry_agriculture_photo"),
        FieldPanel("ministry_environment_photo"),
    ]

    edit_handler = TabbedInterface(
        [
            ObjectList(content_panels, heading=gettext_lazy("Content")),
            ObjectList(promote_panels, heading=gettext_lazy("Promote")),
            ObjectList(plan_panels, heading="plány"),
            ObjectList(archetype_panels, heading="archetypy"),
            ObjectList(ministry_panels, heading="rezorty"),
        ]
    )

    ### RELATIONS

    parent_page_types = ["elections2021.Elections2021HomePage"]
    subpage_types = ["elections2021.Elections2021ProgramPointPage"]

    ### OTHERS

    class Meta:
        verbose_name = "Program"

    def get_meta_image(self):
        return self.search_image or self.photo

    def get_context(self, request):
        context = super().get_context(request)
        context["plan_choices"] = PLAN_CHOICES
        context["ministry_choices"] = MINISTRY_CHOICES
        context["show_archetype_icon"] = True
        context["show_pagination"] = True
        context["active_my_program"] = False
        context["has_my_program"] = (
            Elections2021ProgramAppPage.get_my_selection(request) is not None
        )
        context["show_app_banner"] = not context["has_my_program"]
        return context

    @staticmethod
    def get_archetype_image(archetype):
        return f"elections2021/images/archetype/{archetype}.svg"

    def get_my_program_url(self):
        return self.url + self.reverse_subpage("my_program")

    def get_full_program_url(self):
        return self.url + self.reverse_subpage("full_program")

    @route(r"^$")
    def plan_all(self, request):
        query = request.GET.get("q", None)
        context = {"query": query, "show_app_banner": not query}
        if query:
            points = Elections2021ProgramPointPage.objects.search(query)
        else:
            points = (
                Elections2021ProgramPointPage.objects.live()
                .specific()
                .order_by("-default_order")
            )

        points = Paginator(points, PROGRAM_POINTS_PER_PAGE).get_page(
            request.GET.get("page")
        )
        context["points"] = points
        return self.render(request, context_overrides=context)

    @route(r"^plan/([a-z-]+)/$")
    def plan_detail(self, request, param=None):
        plan = param if param in PLAN_OPTIONS else None
        if not plan:
            return HttpResponseRedirect(self.url)

        title = None
        head_text = ""
        head_image = ""

        if plan:
            title = next(title for key, title in PLAN_CHOICES if key == plan)
            head_image = self.get_archetype_image(PLAN_ARCHETYPES[plan])

        if plan == PLAN_ECONOMICS:
            head_text = self.plan_economics_text
            weights = ["weight_plan_economics"]
        elif plan == PLAN_DIGITAL:
            head_text = self.plan_digital_text
            weights = ["weight_plan_digital"]
        elif plan == PLAN_CORRUPTION:
            head_text = self.plan_corruption_text
            weights = ["weight_plan_corruption"]
        elif plan == PLAN_CLIMATE:
            head_text = self.plan_climate_text
            weights = ["weight_plan_climate"]
        elif plan == PLAN_COUNTRYSIDE:
            head_text = self.plan_countryside_text
            weights = ["weight_plan_countryside"]
        elif plan == PLAN_MANAGEMENT:
            head_text = self.plan_management_text
            weights = ["weight_plan_management"]
        elif plan == PLAN_SAFE_COUNTRY:
            head_text = self.plan_safe_country_text
            weights = ["weight_plan_safe_country"]
        elif plan == PLAN_CARE:
            head_text = self.plan_care_text
            weights = ["weight_plan_care"]

        context = {
            "active_plan": plan,
            "title": title,
            "head_image": head_image,
            "head_text": head_text,
            "points": Elections2021ProgramPointPage.filter_by_weights(weights),
            "show_app_banner": False,
            "show_pagination": False,
        }
        return self.render(request, context_overrides=context)

    @route(r"^resort/([a-z-]+)/$")
    def ministry_detail(self, request, param=None):
        # obrana a zahraničí sloučeny a přesměrovává se na "nové" zahraničí se
        # změněnou adresou na "eu-zahranici-obrana"
        if param in ["obrana", "zahranicni-veci"]:
            url = self.url + self.reverse_subpage(
                "ministry_detail", args=(MINISTRY_FOREIGN,)
            )
            return HttpResponseRedirect(url)

        ministry = param if param in MINISTRY_OPTIONS else None
        if not ministry:
            return HttpResponseRedirect(self.url)

        title = next(title for key, title in MINISTRY_CHOICES if key == ministry)

        if ministry == MINISTRY_TRANSPORT:
            weights = ["weight_ministry_transport"]
            head_photo = self.ministry_transport_photo
        elif ministry == MINISTRY_FINANCES:
            weights = ["weight_ministry_finances"]
            head_photo = self.ministry_finances_photo
        elif ministry == MINISTRY_CULTURE:
            weights = ["weight_ministry_culture"]
            head_photo = self.ministry_culture_photo
        elif ministry == MINISTRY_DEFENSE:
            weights = ["weight_ministry_defense"]
            head_photo = self.ministry_defense_photo
        elif ministry == MINISTRY_SOCIAL:
            weights = ["weight_ministry_social"]
            head_photo = self.ministry_social_photo
        elif ministry == MINISTRY_COUNTRYSIDE:
            weights = ["weight_ministry_countryside"]
            head_photo = self.ministry_countryside_photo
        elif ministry == MINISTRY_BUSINESS:
            weights = ["weight_ministry_business"]
            head_photo = self.ministry_business_photo
        elif ministry == MINISTRY_JUSTICE:
            weights = ["weight_ministry_justice"]
            head_photo = self.ministry_justice_photo
        elif ministry == MINISTRY_SCHOOLS:
            weights = ["weight_ministry_schools"]
            head_photo = self.ministry_schools_photo
        elif ministry == MINISTRY_INTERIOR:
            weights = ["weight_ministry_interior"]
            head_photo = self.ministry_interior_photo
        elif ministry == MINISTRY_FOREIGN:
            weights = ["weight_ministry_foreign"]
            head_photo = self.ministry_foreign_photo
        elif ministry == MINISTRY_HEALTH:
            weights = ["weight_ministry_health"]
            head_photo = self.ministry_health_photo
        elif ministry == MINISTRY_AGRICULTURE:
            weights = ["weight_ministry_agriculture"]
            head_photo = self.ministry_agriculture_photo
        elif ministry == MINISTRY_ENVIRONMENT:
            weights = ["weight_ministry_environment"]
            head_photo = self.ministry_environment_photo

        context = {
            "active_ministry": ministry,
            "title": title,
            "head_photo": head_photo,
            "points": Elections2021ProgramPointPage.filter_by_weights(weights),
            "show_archetype_icon": False,
            "show_app_banner": False,
            "show_pagination": False,
        }
        return self.render(request, context_overrides=context)

    @route(r"^muj-program/$")
    def my_program(self, request):
        selection = Elections2021ProgramAppPage.get_my_selection(request)
        if selection is None:
            response = HttpResponseRedirect(self.url)
            # očekávali jsme data z cookie, ale nepodařilo se je získat, tak pro
            # jistotu cookie smažeme kdyby náhodou existovala s poškozenými daty
            response.delete_cookie(settings.ELECTIONS2021_COOKIE_NAME)
            return response

        weights = []

        archetype = get_archetype(selection)
        if archetype == CHILDLESS:
            weights.append("weight_childless")
            archetype_text = self.archetype_childless_text
            archetype_author_1 = self.archetype_childless_author_1
            archetype_author_2 = self.archetype_childless_author_2
            archetype_photo = self.archetype_childless_photo
        elif archetype == PARENTS:
            weights.append("weight_parents")
            archetype_text = self.archetype_parents_text
            archetype_author_1 = self.archetype_parents_author_1
            archetype_author_2 = self.archetype_parents_author_2
            archetype_photo = self.archetype_parents_photo
        elif archetype == MATURE:
            weights.append("weight_mature")
            archetype_text = self.archetype_mature_text
            archetype_author_1 = self.archetype_mature_author_1
            archetype_author_2 = self.archetype_mature_author_2
            archetype_photo = self.archetype_mature_photo
        elif archetype == STUDENTS:
            weights.append("weight_students")
            archetype_text = self.archetype_students_text
            archetype_author_1 = self.archetype_students_author_1
            archetype_author_2 = self.archetype_students_author_2
            archetype_photo = self.archetype_students_photo
        elif archetype == SENIORS:
            weights.append("weight_seniors")
            archetype_text = self.archetype_seniors_text
            archetype_author_1 = self.archetype_seniors_author_1
            archetype_author_2 = self.archetype_seniors_author_2
            archetype_photo = self.archetype_seniors_photo
        elif archetype == WORKING_SENIORS:
            weights.append("weight_working_seniors")
            archetype_text = self.archetype_working_seniors_text
            archetype_author_1 = self.archetype_working_seniors_author_1
            archetype_author_2 = self.archetype_working_seniors_author_2
            archetype_photo = self.archetype_working_seniors_photo

        if selection["occupation"] == OCCUPATION_BUSINESS:
            weights.append("weight_self_employed")

        if selection["wealth"] == WEALTH_BAD:
            weights.append("weight_socially_weak")

        if NATURE in selection["topics"]:
            weights.append("weight_nature")
        if SPORT in selection["topics"]:
            weights.append("weight_sport")
        if HEALTH in selection["topics"]:
            weights.append("weight_health")
        if CULTURE in selection["topics"]:
            weights.append("weight_culture")
        if TECHNOLOGY in selection["topics"]:
            weights.append("weight_technology")
        if COUNTRYSIDE in selection["topics"]:
            weights.append("weight_countryside")
        if HOUSING in selection["topics"]:
            weights.append("weight_housing")
        if EDUCATION in selection["topics"]:
            weights.append("weight_education")

        points = Elections2021ProgramPointPage.filter_by_weights(weights)
        points = Paginator(points, PROGRAM_POINTS_PER_PAGE).get_page(
            request.GET.get("page")
        )
        context = {
            "title": "Program pro mě",
            "points": points,
            "show_app_banner": False,
            "active_my_program": True,
            "archetype_text": archetype_text,
            "archetype_author_1": archetype_author_1,
            "archetype_author_2": archetype_author_2,
            "archetype_photo": archetype_photo,
        }
        return self.render(request, context_overrides=context)

    @route(r"^kompletni/$")
    def full_program(self, request):
        benefits_titles = dict(BENEFITS_CHOICES)

        toc = []
        body = []

        for ministry, title in MINISTRY_CHOICES:
            sub_toc = []
            points = []
            weight = f"weight_ministry_{MINISTRY_CODES[ministry]}"
            for page in Elections2021ProgramPointPage.filter_by_weights([weight]):
                points.append(page)
                sub_toc.append({"anchor": page.slug, "title": page.title})

            body.append({"anchor": ministry, "title": title, "points": points})
            toc.append({"anchor": ministry, "title": title, "sub_toc": sub_toc})

        context = {"body": body, "toc": toc, "benefits_titles": benefits_titles}
        return self.render(
            request,
            context_overrides=context,
            template="elections2021/elections2021_full_program_page.html",
        )


class QuestionBlock(blocks.StructBlock):
    question = blocks.CharBlock(label="otázka")
    answer = blocks.RichTextBlock(label="odpověď", features=STANDARD_FEATURES)

    class Meta:
        label = "otázka a odpověď"
        icon = "doc-full"
        template = "elections2021/_question_block.html"


class MainBenefitBlock(blocks.StructBlock):
    variant = blocks.ChoiceBlock(BENEFITS_CHOICES, label="název")
    text = blocks.RichTextBlock(label="text", features=STANDARD_FEATURES)

    class Meta:
        label = "hlavní benefit"
        icon = "pick"
        template = "elections2021/_main_benefit_block.html"

    def get_context(self, value, parent_context=None):
        context = super().get_context(value, parent_context=parent_context)
        context["photo"] = f"elections2021/images/benefits/{value['variant']}.jpg"
        context["title"] = next(
            title for num, title in BENEFITS_CHOICES if num == value["variant"]
        )
        return context


class BenefitBlock(blocks.StructBlock):
    title = blocks.CharBlock(label="název")
    text = blocks.RichTextBlock(label="text", features=STANDARD_FEATURES)

    class Meta:
        label = "benefit"
        icon = "pick"
        template = "elections2021/_benefit_block.html"


class Elections2021ProgramPointPage(SubpageMixin, MetadataPageMixin, Page):
    ### FIELDS

    annotation = RichTextField(
        "anotace", blank=True, null=True, features=RESTRICTED_FEATURES
    )
    problem = RichTextField(
        "problém", blank=True, null=True, features=RESTRICTED_FEATURES
    )
    context = RichTextField(
        "kontext problému", blank=True, null=True, features=RESTRICTED_FEATURES
    )
    ideal = RichTextField("ideál", blank=True, null=True, features=RESTRICTED_FEATURES)
    proposal = RichTextField(
        "navrhovaná opatření", blank=True, null=True, features=EXTRA_FEATURES
    )
    time_horizon_text = RichTextField(
        "časový horizont textově", blank=True, null=True, features=STANDARD_FEATURES
    )
    time_horizon_number = models.IntegerField(
        "časový horizont číslo", blank=True, null=True
    )
    time_horizon_unit = models.CharField(
        "časový horizont jednotka", max_length=20, blank=True, null=True
    )
    already_done = RichTextField(
        "co jsme už udělali", blank=True, null=True, features=EXTRA_FEATURES
    )
    sources = RichTextField("zdroje", blank=True, null=True, features=STANDARD_FEATURES)

    faq = StreamField(
        [("question", QuestionBlock())],
        verbose_name="FAQ",
        blank=True,
        use_json_field=True,
    )
    related_points = StreamField(
        [
            (
                "point",
                blocks.PageChooserBlock(
                    label="programový bod",
                    page_type=["elections2021.Elections2021ProgramPointPage"],
                ),
            )
        ],
        verbose_name="související body",
        blank=True,
        use_json_field=True,
    )
    benefit_for_all = RichTextField(
        "benefit pro společnost", blank=True, null=True, features=RESTRICTED_FEATURES
    )
    benefits_main = StreamField(
        [("benefit", MainBenefitBlock())],
        verbose_name="hlavní benefity",
        blank=True,
        use_json_field=True,
    )
    benefits = StreamField(
        [("benefit", BenefitBlock())],
        verbose_name="ostatní benefity",
        blank=True,
        use_json_field=True,
    )

    default_order = models.IntegerField("výchozí řazení", default=0)

    # target weights
    weight_childless = models.IntegerField("váha bezdětní", default=0)
    weight_parents = models.IntegerField("váha rodiče", default=0)
    weight_mature = models.IntegerField("váha zralí", default=0)
    weight_seniors = models.IntegerField("váha senioři", default=0)
    weight_working_seniors = models.IntegerField("váha pracující senioři", default=0)
    weight_students = models.IntegerField("váha studenti", default=0)
    weight_self_employed = models.IntegerField("váha OSVČ", default=0)
    weight_socially_weak = models.IntegerField("váha sociálně slabí", default=0)
    weight_nature = models.IntegerField("váha příroda", default=0)
    weight_sport = models.IntegerField("váha sport", default=0)
    weight_health = models.IntegerField("váha zdraví", default=0)
    weight_culture = models.IntegerField("váha kultura", default=0)
    weight_technology = models.IntegerField("váha technologie", default=0)
    weight_countryside = models.IntegerField("váha regiony", default=0)
    weight_housing = models.IntegerField("váha bydlení", default=0)
    weight_education = models.IntegerField("váha vzdělávání", default=0)
    weight_plan_economics = models.IntegerField("váha moderní ekonomika", default=0)
    weight_plan_digital = models.IntegerField("váha digitalizace státu", default=0)
    weight_plan_corruption = models.IntegerField(
        "váha protikorupční strategie", default=0
    )
    weight_plan_climate = models.IntegerField("váha plán klima", default=0)
    weight_plan_countryside = models.IntegerField("váha plán rozvoj regionů", default=0)
    weight_plan_management = models.IntegerField("váha plán řízení státu", default=0)
    weight_plan_safe_country = models.IntegerField(
        "váha plán sebevědomá země", default=0
    )
    weight_plan_care = models.IntegerField("váha plán jistota péče", default=0)
    weight_ministry_transport = models.IntegerField(
        "váha ministerstvo dopravy", default=0
    )
    weight_ministry_finances = models.IntegerField(
        "váha ministerstvo financí", default=0
    )
    weight_ministry_culture = models.IntegerField(
        "váha ministerstvo kultury", default=0
    )
    weight_ministry_defense = models.IntegerField("váha ministerstvo obrany", default=0)
    weight_ministry_social = models.IntegerField(
        "váha ministerstvo práce a sociálních věcí", default=0
    )
    weight_ministry_countryside = models.IntegerField(
        "váha ministerstvo pro místní rozvoj", default=0
    )
    weight_ministry_business = models.IntegerField(
        "váha ministerstvo průmyslu a obchodu", default=0
    )
    weight_ministry_justice = models.IntegerField(
        "váha ministerstvo spravedlnosti", default=0
    )
    weight_ministry_schools = models.IntegerField(
        "váha ministerstvo školství, mládeže a tělovýchovy", default=0
    )
    weight_ministry_interior = models.IntegerField(
        "váha ministerstvo vnitra", default=0
    )
    weight_ministry_foreign = models.IntegerField(
        "váha ministerstvo zahraničních věcí", default=0
    )
    weight_ministry_health = models.IntegerField(
        "váha ministerstvo zdravotnictví", default=0
    )
    weight_ministry_agriculture = models.IntegerField(
        "váha ministerstvo zemědělství", default=0
    )
    weight_ministry_environment = models.IntegerField(
        "váha ministerstvo životního prostředí", default=0
    )

    ### PANELS

    content_panels = Page.content_panels + [
        FieldPanel("annotation"),
        FieldPanel("problem"),
        FieldPanel("context"),
        FieldPanel("ideal"),
        FieldPanel("proposal"),
        MultiFieldPanel(
            [
                FieldPanel("time_horizon_number"),
                FieldPanel("time_horizon_unit"),
                FieldPanel("time_horizon_text"),
            ],
            "časový horizont",
        ),
        FieldPanel("already_done"),
        FieldPanel("sources"),
    ]

    promote_panels = [
        MultiFieldPanel(
            [
                FieldPanel("slug"),
                FieldPanel("seo_title"),
                FieldPanel("search_description"),
                FieldPanel("search_image"),
                HelpPanel(admin_help.build(admin_help.NO_SEO_TITLE)),
            ],
            gettext_lazy("Common page configuration"),
        ),
        CommentPanel(),
    ]

    faq_panels = [FieldPanel("faq")]

    related_panels = [FieldPanel("related_points")]

    benefits_panels = [
        FieldPanel("benefit_for_all"),
        FieldPanel("benefits_main"),
        FieldPanel("benefits"),
    ]

    weights_panels = [
        FieldPanel("default_order"),
        MultiFieldPanel(
            [
                FieldPanel("weight_childless"),
                FieldPanel("weight_parents"),
                FieldPanel("weight_mature"),
                FieldPanel("weight_seniors"),
                FieldPanel("weight_working_seniors"),
                FieldPanel("weight_students"),
            ],
            "archetypy",
        ),
        MultiFieldPanel(
            [
                FieldPanel("weight_self_employed"),
                FieldPanel("weight_socially_weak"),
            ],
            "doplňující",
        ),
        MultiFieldPanel(
            [
                FieldPanel("weight_nature"),
                FieldPanel("weight_sport"),
                FieldPanel("weight_health"),
                FieldPanel("weight_culture"),
                FieldPanel("weight_technology"),
                FieldPanel("weight_countryside"),
                FieldPanel("weight_housing"),
                FieldPanel("weight_education"),
            ],
            "zájmy",
        ),
        MultiFieldPanel(
            [
                FieldPanel("weight_plan_economics"),
                FieldPanel("weight_plan_digital"),
                FieldPanel("weight_plan_corruption"),
                FieldPanel("weight_plan_climate"),
                FieldPanel("weight_plan_countryside"),
                FieldPanel("weight_plan_management"),
                FieldPanel("weight_plan_safe_country"),
                FieldPanel("weight_plan_care"),
            ],
            "plány",
        ),
        MultiFieldPanel(
            [
                FieldPanel("weight_ministry_transport"),
                FieldPanel("weight_ministry_finances"),
                FieldPanel("weight_ministry_culture"),
                # FieldPanel("weight_ministry_defense"),
                FieldPanel("weight_ministry_social"),
                FieldPanel("weight_ministry_countryside"),
                FieldPanel("weight_ministry_business"),
                FieldPanel("weight_ministry_justice"),
                FieldPanel("weight_ministry_schools"),
                FieldPanel("weight_ministry_interior"),
                FieldPanel("weight_ministry_foreign"),
                FieldPanel("weight_ministry_health"),
                FieldPanel("weight_ministry_agriculture"),
                FieldPanel("weight_ministry_environment"),
            ],
            "ministerstva",
        ),
    ]

    import_panels = [
        MultiFieldPanel(
            [
                FieldPanel("import_file"),
                HelpPanel(
                    'Soubor z Goodle Docs stáhněte jako "Webová stránka (komprimovaný '
                    ' HTML soubor)" a ten nahrajte do formuláře.'
                ),
            ],
            "import programového bodu",
        ),
    ]

    edit_handler = TabbedInterface(
        [
            ObjectList(content_panels, heading=gettext_lazy("Content")),
            ObjectList(promote_panels, heading=gettext_lazy("Promote")),
            ObjectList(faq_panels, heading="FAQ"),
            ObjectList(benefits_panels, heading="benefity"),
            ObjectList(related_panels, heading="související"),
            ObjectList(weights_panels, heading="váhy"),
            ObjectList(import_panels, heading="import"),
        ]
    )

    ### RELATIONS

    parent_page_types = ["elections2021.Elections2021ProgramPage"]
    subpage_types = []

    ### SEARCH

    search_fields = Page.search_fields + [
        index.SearchField("annotation", boost=1.6),
        index.SearchField("problem"),
        index.SearchField("context"),
        index.SearchField("ideal"),
        index.SearchField("proposal"),
    ]

    ### OTHERS

    base_form_class = ProgramPointPageForm

    class Meta:
        verbose_name = "Programový bod"

    def get_meta_description(self):
        if self.search_description:
            return self.search_description
        return re.sub(r"<.*?>|\[.*?\]", "", self.annotation)

    @property
    def archetype(self):
        if self.weight_ministry_transport:
            return MINISTRY_ARCHETYPES[MINISTRY_TRANSPORT]
        if self.weight_ministry_finances:
            return MINISTRY_ARCHETYPES[MINISTRY_FINANCES]
        if self.weight_ministry_culture:
            return MINISTRY_ARCHETYPES[MINISTRY_CULTURE]
        if self.weight_ministry_defense:
            return MINISTRY_ARCHETYPES[MINISTRY_DEFENSE]
        if self.weight_ministry_social:
            return MINISTRY_ARCHETYPES[MINISTRY_SOCIAL]
        if self.weight_ministry_countryside:
            return MINISTRY_ARCHETYPES[MINISTRY_COUNTRYSIDE]
        if self.weight_ministry_business:
            return MINISTRY_ARCHETYPES[MINISTRY_BUSINESS]
        if self.weight_ministry_justice:
            return MINISTRY_ARCHETYPES[MINISTRY_JUSTICE]
        if self.weight_ministry_schools:
            return MINISTRY_ARCHETYPES[MINISTRY_SCHOOLS]
        if self.weight_ministry_interior:
            return MINISTRY_ARCHETYPES[MINISTRY_INTERIOR]
        if self.weight_ministry_foreign:
            return MINISTRY_ARCHETYPES[MINISTRY_FOREIGN]
        if self.weight_ministry_health:
            return MINISTRY_ARCHETYPES[MINISTRY_HEALTH]
        if self.weight_ministry_agriculture:
            return MINISTRY_ARCHETYPES[MINISTRY_AGRICULTURE]
        if self.weight_ministry_environment:
            return MINISTRY_ARCHETYPES[MINISTRY_ENVIRONMENT]
        return ""

    @classmethod
    def filter_by_weights(cls, weights):
        points = cls.objects.live().specific()
        if len(weights) > 1:
            return (
                points.annotate(max_weight=Greatest(*weights))
                .filter(max_weight__gt=0)
                .order_by("-max_weight")
            )
        else:
            condition = {f"{weights[0]}__gt": 0}
            order = f"-{weights[0]}"
            return points.filter(**condition).order_by(order)


class RichQuestionBlock(blocks.StructBlock):
    question = blocks.CharBlock(label="otázka")
    answer = blocks.RichTextBlock(label="odpověď", features=ARTICLE_RICH_TEXT_FEATURES)

    class Meta:
        label = "otázka a odpověď"
        icon = "doc-full"
        template = "elections2021/_rich_question_block.html"


class Elections2021QuestionsPage(SubpageMixin, MetadataPageMixin, Page):
    ### FIELDS

    intro = RichTextField(
        "úvodní text", blank=True, features=ARTICLE_RICH_TEXT_FEATURES
    )
    photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="hlavní fotka",
    )
    myths = StreamField(
        [("question", RichQuestionBlock())],
        verbose_name="mýty o koalici",
        blank=True,
        use_json_field=True,
    )
    elections = StreamField(
        [("question", RichQuestionBlock())],
        verbose_name="otázky k volbám",
        blank=True,
        use_json_field=True,
    )

    ### PANELS

    content_panels = Page.content_panels + [
        FieldPanel("intro"),
        FieldPanel("photo"),
    ]

    promote_panels = [
        MultiFieldPanel(
            [
                FieldPanel("slug"),
                FieldPanel("seo_title"),
                FieldPanel("search_description"),
                FieldPanel("search_image"),
                HelpPanel(
                    admin_help.build(admin_help.NO_SEO_TITLE, NO_SEARCH_IMAGE_USE_PHOTO)
                ),
            ],
            gettext_lazy("Common page configuration"),
        ),
        CommentPanel(),
    ]

    myths_panels = [FieldPanel("myths")]

    elections_panels = [FieldPanel("elections")]

    edit_handler = TabbedInterface(
        [
            ObjectList(content_panels, heading=gettext_lazy("Content")),
            ObjectList(myths_panels, heading="mýty"),
            ObjectList(elections_panels, heading="volby"),
            ObjectList(promote_panels, heading=gettext_lazy("Promote")),
        ]
    )

    ### RELATIONS

    parent_page_types = ["elections2021.Elections2021HomePage"]
    subpage_types = []

    ### OTHERS

    class Meta:
        verbose_name = "FAQ"

    def get_meta_image(self):
        return self.search_image or self.photo


class Elections2021ProgramAppPage(SubpageMixin, MetadataPageMixin, Page):
    ### FIELDS

    info_title = models.CharField(
        "titulek k informacím", blank=True, null=True, max_length=255
    )
    info_text = RichTextField(
        "základní informace", blank=True, null=True, features=RESTRICTED_FEATURES
    )

    ### PANELS

    content_panels = Page.content_panels + [
        FieldPanel("info_title"),
        FieldPanel("info_text"),
    ]

    promote_panels = [
        MultiFieldPanel(
            [
                FieldPanel("slug"),
                FieldPanel("seo_title"),
                FieldPanel("search_description"),
                FieldPanel("search_image"),
                HelpPanel(admin_help.build(admin_help.NO_SEO_TITLE)),
            ],
            gettext_lazy("Common page configuration"),
        ),
        CommentPanel(),
    ]

    settings_panels = []

    ### RELATIONS

    parent_page_types = ["elections2021.Elections2021HomePage"]
    subpage_types = []

    ### OTHERS

    class Meta:
        verbose_name = "Programová aplikace"

    def serve(self, request, *args, **kwargs):
        if request.method == "POST":
            form = ProgramAppForm(request.POST)
            if form.is_valid():
                program_page = Elections2021ProgramPage.objects.live().first()
                response = HttpResponseRedirect(program_page.get_my_program_url())
                response.set_signed_cookie(
                    settings.ELECTIONS2021_COOKIE_NAME,
                    json.dumps(form.cleaned_data),
                    secure=settings.SESSION_COOKIE_SECURE,
                    httponly=settings.SESSION_COOKIE_HTTPONLY,
                )
                return response
        return super().serve(request, *args, **kwargs)

    @staticmethod
    def get_my_selection(request):
        data = request.get_signed_cookie(settings.ELECTIONS2021_COOKIE_NAME, None)
        if data:
            try:
                return json.loads(data)
            except json.JSONDecodeError:
                pass
        return None

    def get_context(self, request):
        context = super().get_context(request)
        selection = self.get_my_selection(request)
        if selection is None:
            selection = {
                "age": AGE_30_49,
                "kids": True,
                "wealth": WEALTH_AVERAGE,
                "occupation": OCCUPATION_WORKING,
                "topics": [],
            }
        context["active"] = {
            "age": selection["age"],
            "kids": selection["kids"],
            "wealth": selection["wealth"],
            "occupation": selection["occupation"],
            "nature": NATURE in selection["topics"],
            "sport": SPORT in selection["topics"],
            "health": HEALTH in selection["topics"],
            "culture": CULTURE in selection["topics"],
            "technology": TECHNOLOGY in selection["topics"],
            "countryside": COUNTRYSIDE in selection["topics"],
            "housing": HOUSING in selection["topics"],
            "education": EDUCATION in selection["topics"],
        }
        return context


class Elections2021TextPage(SubpageMixin, MetadataPageMixin, Page):
    ### FIELDS

    body = RichTextField(
        "obsah stránky", blank=True, null=True, features=ARTICLE_RICH_TEXT_FEATURES
    )

    ### PANELS

    content_panels = Page.content_panels + [FieldPanel("body")]

    promote_panels = [
        MultiFieldPanel(
            [
                FieldPanel("slug"),
                FieldPanel("seo_title"),
                FieldPanel("search_description"),
                FieldPanel("search_image"),
                HelpPanel(admin_help.build(admin_help.NO_SEO_TITLE)),
            ],
            gettext_lazy("Common page configuration"),
        ),
        CommentPanel(),
    ]

    settings_panels = []

    ### RELATIONS

    parent_page_types = ["elections2021.Elections2021HomePage"]
    subpage_types = []

    ### OTHERS

    class Meta:
        verbose_name = "Textová stránka"


class Elections2021StrategicListPage(SubpageMixin, MetadataPageMixin, Page):
    ### FIELDS

    ### PANELS

    promote_panels = [
        MultiFieldPanel(
            [
                FieldPanel("slug"),
                FieldPanel("seo_title"),
                FieldPanel("search_description"),
                FieldPanel("search_image"),
                HelpPanel(admin_help.build(admin_help.NO_SEO_TITLE)),
            ],
            gettext_lazy("Common page configuration"),
        ),
        CommentPanel(),
    ]

    settings_panels = []

    ### RELATIONS

    parent_page_types = ["elections2021.Elections2021HomePage"]
    subpage_types = ["elections2021.Elections2021StrategicPage"]

    ### OTHERS

    class Meta:
        verbose_name = "Strategické dokumenty"

    def get_context(self, request):
        context = super().get_context(request)
        context["strategic_documents"] = Paginator(
            self.get_children().live().specific(), STRATEGIC_PER_PAGE
        ).get_page(request.GET.get("page"))
        return context


class Elections2021StrategicPage(SubpageMixin, MetadataPageMixin, Page):
    ### FIELDS

    card_style = models.CharField(
        "styl karty v přehledu", choices=STYLE_CHOICES, default=WHITE, max_length=10
    )
    perex = models.TextField("perex")
    content = StreamField(
        [
            (
                "title",
                blocks.CharBlock(
                    label="nadpis sekce (pro navigaci)",
                    icon="title",
                    template="elections2021/_strategic_title_block.html",
                ),
            ),
            (
                "text",
                blocks.RichTextBlock(
                    label="text",
                    features=STRATEGIC_RICH_TEXT_FEATURES,
                    template="elections2021/_strategic_text_block.html",
                ),
            ),
        ],
        verbose_name="obsah stránky",
        blank=True,
        use_json_field=True,
    )

    ### PANELS

    content_panels = Page.content_panels + [
        FieldPanel("perex"),
        FieldPanel("content"),
        FieldPanel("card_style"),
    ]

    promote_panels = [
        MultiFieldPanel(
            [
                FieldPanel("slug"),
                FieldPanel("seo_title"),
                FieldPanel("search_description"),
                FieldPanel("search_image"),
                HelpPanel(admin_help.build(admin_help.NO_SEO_TITLE)),
            ],
            gettext_lazy("Common page configuration"),
        ),
    ]

    settings_panels = [PublishingPanel(), CommentPanel()]

    ### RELATIONS

    parent_page_types = ["elections2021.Elections2021StrategicListPage"]
    subpage_types = []

    ### OTHERS

    class Meta:
        verbose_name = "Strategický dokument"

    def get_context(self, request):
        context = super().get_context(request)
        context["navigation"] = []
        for block in self.content:
            if block.block_type == "title":
                context["navigation"].append((slugify(block.value), block.value))
        return context


class Elections2021MythsPage(SubpageMixin, MetadataPageMixin, Page):
    ### FIELDS

    ### PANELS

    promote_panels = [
        MultiFieldPanel(
            [
                FieldPanel("slug"),
                FieldPanel("seo_title"),
                FieldPanel("search_description"),
                FieldPanel("search_image"),
                HelpPanel(admin_help.build(admin_help.NO_SEO_TITLE)),
            ],
            gettext_lazy("Common page configuration"),
        ),
        CommentPanel(),
    ]

    settings_panels = []

    ### RELATIONS

    parent_page_types = ["elections2021.Elections2021HomePage"]
    subpage_types = ["elections2021.Elections2021MythPage"]

    ### OTHERS

    class Meta:
        verbose_name = "Nejčastější mýty"

    def get_context(self, request):
        context = super().get_context(request)
        context["myths"] = self.get_children().live().specific()
        return context


class Elections2021MythPage(SubpageMixin, MetadataPageMixin, Page):
    ### FIELDS

    perex = models.TextField("perex")
    myth = RichTextField(
        "co se říká?", blank=True, null=True, features=STRATEGIC_RICH_TEXT_FEATURES
    )
    reality = RichTextField(
        "co ve skutečnosti prosazujeme",
        blank=True,
        null=True,
        features=STRATEGIC_RICH_TEXT_FEATURES,
    )
    related_points = StreamField(
        [
            (
                "point",
                blocks.PageChooserBlock(
                    label="programový bod",
                    page_type=["elections2021.Elections2021ProgramPointPage"],
                ),
            )
        ],
        verbose_name="související programové body",
        blank=True,
        use_json_field=True,
    )

    ### PANELS

    content_panels = Page.content_panels + [
        FieldPanel("perex"),
        FieldPanel("myth"),
        FieldPanel("reality"),
        FieldPanel("related_points"),
    ]

    promote_panels = [
        MultiFieldPanel(
            [
                FieldPanel("slug"),
                FieldPanel("seo_title"),
                FieldPanel("search_description"),
                HelpPanel(
                    admin_help.build(
                        admin_help.NO_SEO_TITLE, admin_help.NO_DESCRIPTION_USE_PEREX
                    )
                ),
            ],
            gettext_lazy("Common page configuration"),
        ),
        CommentPanel(),
    ]

    settings_panels = []

    ### RELATIONS

    parent_page_types = ["elections2021.Elections2021MythsPage"]
    subpage_types = []

    ### OTHERS

    class Meta:
        verbose_name = "Mýtus"

    def get_meta_description(self):
        if self.search_description:
            return self.search_description
        if len(self.perex) > 150:
            return str(self.perex)[:150] + "..."
        return self.perex


class DownloadDocumentBlock(blocks.StructBlock):
    title = blocks.CharBlock(label="název")
    photo = ImageChooserBlock(label="náhled")
    document = DocumentChooserBlock(label="dokument")

    class Meta:
        label = "dokument ke stažení"
        icon = "doc-full"
        template = "elections2021/_download_document_block.html"

    def get_context(self, value, parent_context=None):
        context = super().get_context(value, parent_context=parent_context)
        ext = value["document"].url.lower().split(".")[-1]
        context["icon"] = f"elections2021/images/pretty-file-icons/svg/{ext}.svg"
        return context


class DownloadSpotifyBlock(blocks.StructBlock):
    title = blocks.CharBlock(label="název")
    photo = ImageChooserBlock(label="náhled")
    url = blocks.URLBlock(label="odkaz na Spotify")

    class Meta:
        label = "odkaz na Spotify"
        icon = "media"
        template = "elections2021/_download_spotify_block.html"


class DownloadTextDocumentBlock(blocks.StructBlock):
    title = blocks.CharBlock(label="název")
    document = DocumentChooserBlock(label="dokument")

    class Meta:
        label = "dokument ke stažení"
        icon = "doc-full"


class Elections2021DownloadsPage(SubpageMixin, MetadataPageMixin, Page):
    ### FIELDS

    downloads = StreamField(
        [("document", DownloadDocumentBlock()), ("spotify", DownloadSpotifyBlock())],
        verbose_name="soubory ke stažení",
        blank=True,
        use_json_field=True,
    )
    text_downloads = StreamField(
        [("document", DownloadTextDocumentBlock())],
        verbose_name="textové soubory ke stažení",
        blank=True,
        use_json_field=True,
    )

    ### PANELS

    content_panels = Page.content_panels + [
        FieldPanel("downloads"),
        FieldPanel("text_downloads"),
    ]

    promote_panels = [
        MultiFieldPanel(
            [
                FieldPanel("slug"),
                FieldPanel("seo_title"),
                FieldPanel("search_description"),
                FieldPanel("search_image"),
                HelpPanel(admin_help.build(admin_help.NO_SEO_TITLE)),
            ],
            gettext_lazy("Common page configuration"),
        ),
        CommentPanel(),
    ]

    settings_panels = []

    ### RELATIONS

    parent_page_types = ["elections2021.Elections2021HomePage"]
    subpage_types = []

    ### OTHERS

    class Meta:
        verbose_name = "Soubory ke stažení"


class GovernmentTeamMemberBlock(blocks.StructBlock):
    name = blocks.CharBlock(label="jméno")
    photo = ImageChooserBlock(label="fotka")
    occupation = blocks.CharBlock(label="povolání")
    resume = blocks.TextBlock(label="medailonek")

    class Meta:
        label = "člen vládního týmu"
        icon = "user"
        template = "elections2021/_government_team_member_block.html"


class GovernmentSectionBlock(blocks.StructBlock):
    title = blocks.CharBlock(label="název")
    members = blocks.ListBlock(GovernmentTeamMemberBlock())

    class Meta:
        label = "sekce vládního týmu"
        icon = "group"
        template = "elections2021/_government_section_block.html"


class Elections2021GovernmentTeamPage(SubpageMixin, MetadataPageMixin, Page):
    ### FIELDS

    photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="hlavní fotka",
    )
    sections = StreamField(
        [("section", GovernmentSectionBlock())],
        verbose_name="sekce vládního týmu",
        blank=True,
        use_json_field=True,
    )

    ### PANELS

    content_panels = Page.content_panels + [
        FieldPanel("photo"),
        FieldPanel("sections"),
    ]

    promote_panels = [
        MultiFieldPanel(
            [
                FieldPanel("slug"),
                FieldPanel("seo_title"),
                FieldPanel("search_description"),
                FieldPanel("search_image"),
                HelpPanel(
                    admin_help.build(admin_help.NO_SEO_TITLE, NO_SEARCH_IMAGE_USE_PHOTO)
                ),
            ],
            gettext_lazy("Common page configuration"),
        ),
        CommentPanel(),
    ]

    settings_panels = []

    ### RELATIONS

    parent_page_types = ["elections2021.Elections2021HomePage"]
    subpage_types = []

    ### OTHERS

    class Meta:
        verbose_name = "Vládní tým"

    def get_meta_image(self):
        return self.search_image or self.photo


class Elections2021CalendarPage(SubpageMixin, MetadataPageMixin, CalendarMixin, Page):
    ### FIELDS

    photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="hlavní fotka",
    )

    ### PANELS

    content_panels = Page.content_panels + [
        FieldPanel("photo"),
        FieldPanel("calendar_url"),
    ]

    promote_panels = [
        MultiFieldPanel(
            [
                FieldPanel("slug"),
                FieldPanel("seo_title"),
                FieldPanel("search_description"),
                FieldPanel("search_image"),
                HelpPanel(
                    admin_help.build(admin_help.NO_SEO_TITLE, NO_SEARCH_IMAGE_USE_PHOTO)
                ),
            ],
            gettext_lazy("Common page configuration"),
        ),
        CommentPanel(),
    ]

    settings_panels = []

    ### RELATIONS

    parent_page_types = ["elections2021.Elections2021HomePage"]
    subpage_types = []

    ### OTHERS

    class Meta:
        verbose_name = "Kalendář"

    def get_meta_image(self):
        return self.search_image or self.photo

    @property
    def has_calendar(self):
        return self.calendar_id is not None

    def get_calendar(self):
        for event in self.calendar.future_events:
            event["pir"] = {"name": None, "tags": [], "region": None}

            pir_name = []

            for word in event.get("name", "").split():
                if word.startswith("#"):
                    event["pir"]["tags"].append(word[1:])
                else:
                    pir_name.append(word)

            if len(pir_name) > 0:
                if pir_name[0].endswith(":") and len(pir_name[0]) == 4:
                    event["pir"]["region"] = pir_name.pop(0)[:-1]

            event["pir"]["name"] = " ".join(pir_name)

        return self.calendar


class Token(models.Model):
    scope = models.CharField(max_length=127)
    bearer = models.CharField(max_length=40)
    comment = models.CharField(max_length=255)


class BannerBlock(blocks.StructBlock):
    code = blocks.CharBlock(label="kód banneru")
    candidate1 = blocks.CharBlock(label="první kandidát", required=False)
    candidate2 = blocks.CharBlock(label="druhý kandidát", required=False)
    tagline = blocks.CharBlock(label="slogan", required=False)
    preview = ImageChooserBlock(label="náhled")

    class Meta:
        label = "plachta"
        icon = "flag"
        template = "elections2021/_banner_block.html"


class BannerOrder(models.Model):
    code = models.CharField(max_length=10)
    name = models.CharField(max_length=35)
    surname = models.CharField(max_length=70)
    residency = models.CharField(max_length=70)
    date_of_birth = models.DateField()
    phone = models.CharField(max_length=20)
    email = models.EmailField(max_length=70)
    note = models.CharField(max_length=255, blank=True)


class BannerForm(forms.ModelForm):
    class Meta:
        model = BannerOrder
        fields = [
            "code",
            "name",
            "surname",
            "residency",
            "date_of_birth",
            "phone",
            "email",
            "note",
        ]


class Elections2021BannerListPage(
    SubpageMixin, MetadataPageMixin, RoutablePageMixin, Page
):
    ### FIELDS

    subtitle = models.CharField(max_length=100, blank=True, verbose_name="podtitulek")
    banners = StreamField(
        [("banners", BannerBlock())],
        verbose_name="objednávání plachet",
        blank=True,
        use_json_field=True,
    )

    ### PANELS

    content_panels = Page.content_panels + [
        FieldPanel("subtitle"),
        FieldPanel("banners"),
    ]

    promote_panels = [
        MultiFieldPanel(
            [
                FieldPanel("slug"),
                FieldPanel("seo_title"),
                FieldPanel("search_description"),
                FieldPanel("search_image"),
                HelpPanel(
                    admin_help.build(admin_help.NO_SEO_TITLE, NO_SEARCH_IMAGE_USE_PHOTO)
                ),
            ],
            gettext_lazy("Common page configuration"),
        ),
        CommentPanel(),
    ]

    settings_panels = []

    ### RELATIONS

    parent_page_types = ["elections2021.Elections2021MapPage"]
    subpage_types = []

    ### OTHERS

    class Meta:
        verbose_name = "nabídka plachet"

    def serve(self, request, *args, **kwargs):
        if request.method == "POST":
            form = BannerForm(request.POST)
            form.has_been_saved = False

            if form.is_valid():
                form.save()
                form.has_been_saved = True
        else:
            form = BannerForm()
            form.has_been_saved = False

        request.banner_form = form
        return super().serve(request, *args, **kwargs)


class Elections2021MapPage(SubpageMixin, MetadataPageMixin, Page):
    ### FIELDS

    subtitle = models.CharField(max_length=100, blank=True, verbose_name="podtitulek")

    praha = models.ForeignKey(
        "wagtailcore.Page",
        verbose_name="Praha",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )

    stredocesky = models.ForeignKey(
        "wagtailcore.Page",
        verbose_name="Středočeský",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )

    jihocesky = models.ForeignKey(
        "wagtailcore.Page",
        verbose_name="Jihočeský",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )

    plzensky = models.ForeignKey(
        "wagtailcore.Page",
        verbose_name="Plzeňský",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )

    karlovarsky = models.ForeignKey(
        "wagtailcore.Page",
        verbose_name="Karlovarský",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )

    ustecky = models.ForeignKey(
        "wagtailcore.Page",
        verbose_name="Ústecký",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )

    liberecky = models.ForeignKey(
        "wagtailcore.Page",
        verbose_name="Liberecký",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )

    kralovehradecky = models.ForeignKey(
        "wagtailcore.Page",
        verbose_name="Královéhradecký",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )

    moravskoslezsky = models.ForeignKey(
        "wagtailcore.Page",
        verbose_name="Moravskoslezský",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )

    pardubicky = models.ForeignKey(
        "wagtailcore.Page",
        verbose_name="Pardubický",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )

    vysocina = models.ForeignKey(
        "wagtailcore.Page",
        verbose_name="Vysočina",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )

    jihomoravsky = models.ForeignKey(
        "wagtailcore.Page",
        verbose_name="Jihomoravsý",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )

    olomoucky = models.ForeignKey(
        "wagtailcore.Page",
        verbose_name="Olomoucký",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )

    zlinsky = models.ForeignKey(
        "wagtailcore.Page",
        verbose_name="Zlínský",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )

    ### PANELS

    content_panels = Page.content_panels + [
        FieldPanel("subtitle"),
        MultiFieldPanel(
            [
                PageChooserPanel("praha", "wagtailcore.Page"),
                PageChooserPanel("stredocesky", "wagtailcore.Page"),
                PageChooserPanel("jihocesky", "wagtailcore.Page"),
                PageChooserPanel("plzensky", "wagtailcore.Page"),
                PageChooserPanel("karlovarsky", "wagtailcore.Page"),
                PageChooserPanel("ustecky", "wagtailcore.Page"),
                PageChooserPanel("liberecky", "wagtailcore.Page"),
                PageChooserPanel("kralovehradecky", "wagtailcore.Page"),
                PageChooserPanel("moravskoslezsky", "wagtailcore.Page"),
                PageChooserPanel("pardubicky", "wagtailcore.Page"),
                PageChooserPanel("vysocina", "wagtailcore.Page"),
                PageChooserPanel("jihomoravsky", "wagtailcore.Page"),
                PageChooserPanel("olomoucky", "wagtailcore.Page"),
                PageChooserPanel("zlinsky", "wagtailcore.Page"),
            ],
            "Rozcestník krajů",
        ),
    ]

    promote_panels = [
        MultiFieldPanel(
            [
                FieldPanel("slug"),
                FieldPanel("seo_title"),
                FieldPanel("search_description"),
                FieldPanel("search_image"),
                HelpPanel(
                    admin_help.build(admin_help.NO_SEO_TITLE, NO_SEARCH_IMAGE_USE_PHOTO)
                ),
            ],
            gettext_lazy("Common page configuration"),
        ),
        CommentPanel(),
    ]

    settings_panels = []

    ### RELATIONS

    parent_page_types = ["elections2021.Elections2021HomePage"]
    subpage_types = ["elections2021.Elections2021BannerListPage"]

    ### OTHERS

    class Meta:
        verbose_name = "mapa krajů"


class NutshellItemBlock(blocks.StructBlock):
    text = blocks.TextBlock(label="text")
    points = blocks.ListBlock(
        blocks.StructBlock(
            [
                ("title", blocks.TextBlock(label="titulek")),
                (
                    "point",
                    blocks.PageChooserBlock(
                        label="programový bod",
                        page_type=["elections2021.Elections2021ProgramPointPage"],
                    ),
                ),
            ]
        ),
        label="programové body",
    )

    class Meta:
        label = "blok programu v kostce"
        template = "elections2021/_nutshell_item_block.html"


class NutshellSectionBlock(blocks.StructBlock):
    title = blocks.CharBlock(label="nadpis")
    items = blocks.ListBlock(NutshellItemBlock(), label="bloky")

    class Meta:
        label = "sekce programu v kostce"
        template = "elections2021/_nutshell_section_block.html"


class Elections2021ProgramInNutshellPage(SubpageMixin, MetadataPageMixin, Page):
    ### FIELDS

    leading = models.TextField("úvod", blank=True, null=True)
    subtitle = models.CharField("podnadpis", blank=True, null=True, max_length=255)
    body = RichTextField(
        "obsah", blank=True, null=True, features=ARTICLE_RICH_TEXT_FEATURES
    )
    content = StreamField(
        [("section", NutshellSectionBlock())],
        verbose_name="sekce",
        blank=True,
        use_json_field=True,
    )

    ### PANELS

    content_panels = Page.content_panels + [
        FieldPanel("leading"),
        FieldPanel("subtitle"),
        FieldPanel("body"),
        FieldPanel("content"),
    ]

    promote_panels = [
        MultiFieldPanel(
            [
                FieldPanel("slug"),
                FieldPanel("seo_title"),
                FieldPanel("search_description"),
                FieldPanel("search_image"),
                HelpPanel(admin_help.build(admin_help.NO_SEO_TITLE)),
            ],
            gettext_lazy("Common page configuration"),
        ),
        CommentPanel(),
    ]

    settings_panels = []

    ### RELATIONS

    parent_page_types = ["elections2021.Elections2021HomePage"]
    subpage_types = []

    ### OTHERS

    class Meta:
        verbose_name = "Program v kostce"


class Elections2021GoingToVotePage(SubpageMixin, MetadataPageMixin, Page):
    ### FIELDS

    subtitle = models.CharField("podnadpis", blank=True, null=True, max_length=255)
    header_text = RichTextField(
        "text v hlavičce", blank=True, null=True, features=ARTICLE_RICH_TEXT_FEATURES
    )
    video = models.URLField("video na youtube", blank=True, null=True)
    bottom_title = models.CharField(
        "spodní nadpis", blank=True, null=True, max_length=255
    )
    bottom_text = RichTextField(
        "spodní obsah", blank=True, null=True, features=ARTICLE_RICH_TEXT_FEATURES
    )

    section1_title = models.CharField("titulek", blank=True, null=True, max_length=255)
    section1_text = RichTextField(
        "program", blank=True, null=True, features=ARTICLE_RICH_TEXT_FEATURES
    )
    section1_image = models.ForeignKey(
        "wagtailimages.Image",
        verbose_name="obrázek",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )
    section2_title = models.CharField("titulek", blank=True, null=True, max_length=255)
    section2_text = RichTextField(
        "program", blank=True, null=True, features=ARTICLE_RICH_TEXT_FEATURES
    )
    section2_image = models.ForeignKey(
        "wagtailimages.Image",
        verbose_name="obrázek",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )
    section3_title = models.CharField("titulek", blank=True, null=True, max_length=255)
    section3_text = RichTextField(
        "program", blank=True, null=True, features=ARTICLE_RICH_TEXT_FEATURES
    )
    section3_image = models.ForeignKey(
        "wagtailimages.Image",
        verbose_name="obrázek",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )
    section4_title = models.CharField("titulek", blank=True, null=True, max_length=255)
    section4_text = RichTextField(
        "program", blank=True, null=True, features=ARTICLE_RICH_TEXT_FEATURES
    )
    section4_image = models.ForeignKey(
        "wagtailimages.Image",
        verbose_name="obrázek",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )
    section6_title = models.CharField("titulek", blank=True, null=True, max_length=255)
    section6_text = RichTextField(
        "program", blank=True, null=True, features=ARTICLE_RICH_TEXT_FEATURES
    )
    section6_image = models.ForeignKey(
        "wagtailimages.Image",
        verbose_name="obrázek",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )
    section7_title = models.CharField("titulek", blank=True, null=True, max_length=255)
    section7_text = RichTextField(
        "program", blank=True, null=True, features=ARTICLE_RICH_TEXT_FEATURES
    )
    section7_image = models.ForeignKey(
        "wagtailimages.Image",
        verbose_name="obrázek",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )
    section8_title = models.CharField("titulek", blank=True, null=True, max_length=255)
    section8_text = RichTextField(
        "program", blank=True, null=True, features=ARTICLE_RICH_TEXT_FEATURES
    )
    section8_image = models.ForeignKey(
        "wagtailimages.Image",
        verbose_name="obrázek",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )
    section9_title = models.CharField("titulek", blank=True, null=True, max_length=255)
    section9_text = RichTextField(
        "program", blank=True, null=True, features=ARTICLE_RICH_TEXT_FEATURES
    )
    section9_image = models.ForeignKey(
        "wagtailimages.Image",
        verbose_name="obrázek",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )

    ### PANELS

    content_panels = Page.content_panels + [
        FieldPanel("subtitle"),
        FieldPanel("header_text"),
        FieldPanel("video"),
        MultiFieldPanel(
            [FieldPanel("bottom_title"), FieldPanel("bottom_text")], "spodní obsah"
        ),
        MultiFieldPanel(
            [
                FieldPanel("section1_title"),
                FieldPanel("section1_text"),
                FieldPanel("section1_image"),
            ],
            "sekce 1",
        ),
        MultiFieldPanel(
            [
                FieldPanel("section2_title"),
                FieldPanel("section2_text"),
                FieldPanel("section2_image"),
            ],
            "sekce 2",
        ),
        MultiFieldPanel(
            [
                FieldPanel("section3_title"),
                FieldPanel("section3_text"),
                FieldPanel("section3_image"),
            ],
            "sekce 3",
        ),
        MultiFieldPanel(
            [
                FieldPanel("section4_title"),
                FieldPanel("section4_text"),
                FieldPanel("section4_image"),
            ],
            "sekce 4",
        ),
        MultiFieldPanel(
            [
                FieldPanel("section6_title"),
                FieldPanel("section6_text"),
                FieldPanel("section6_image"),
            ],
            "sekce 6",
        ),
        MultiFieldPanel(
            [
                FieldPanel("section7_title"),
                FieldPanel("section7_text"),
                FieldPanel("section7_image"),
            ],
            "sekce 7",
        ),
        MultiFieldPanel(
            [
                FieldPanel("section8_title"),
                FieldPanel("section8_text"),
                FieldPanel("section8_image"),
            ],
            "sekce 8",
        ),
        MultiFieldPanel(
            [
                FieldPanel("section9_title"),
                FieldPanel("section9_text"),
                FieldPanel("section9_image"),
            ],
            "sekce 9",
        ),
    ]

    promote_panels = [
        MultiFieldPanel(
            [
                FieldPanel("slug"),
                FieldPanel("seo_title"),
                FieldPanel("search_description"),
                FieldPanel("search_image"),
                HelpPanel(admin_help.build(admin_help.NO_SEO_TITLE)),
            ],
            gettext_lazy("Common page configuration"),
        ),
        CommentPanel(),
    ]

    settings_panels = []

    ### RELATIONS

    parent_page_types = ["elections2021.Elections2021HomePage"]
    subpage_types = []

    ### OTHERS

    class Meta:
        verbose_name = "Jdeme k volbám"