from django import forms
from django.db import models
from django.utils.translation import gettext_lazy
from wagtail.admin.edit_handlers import (
    FieldPanel,
    HelpPanel,
    MultiFieldPanel,
    StreamFieldPanel,
)
from wagtail.contrib.table_block.blocks import TableBlock
from wagtail.core import blocks
from wagtail.core.fields import StreamField
from wagtail.core.models import Page
from wagtail.documents.blocks import DocumentChooserBlock
from wagtail.images.blocks import ImageChooserBlock
from wagtail.images.edit_handlers import ImageChooserPanel
from wagtailmetadata.models import MetadataPageMixin

from tuning import help

from .constants import (
    ALIGN_CHOICES,
    ALIGN_CSS,
    BLACK_ON_WHITE,
    COLOR_CHOICES,
    COLOR_CSS,
    LEFT,
    RICH_TEXT_FEATURES,
)


class ColorBlock(blocks.StructBlock):
    """
    Intended as parent class for blocks with color option.
    """

    color = blocks.ChoiceBlock(COLOR_CHOICES, label="barva", default=BLACK_ON_WHITE)

    def get_context(self, value, parent_context=None):
        context = super().get_context(value, parent_context=parent_context)
        if "css_class" not in context:
            context["css_class"] = []
        context["css_class"] += COLOR_CSS[value["color"]]
        return context


class AlignBlock(blocks.StructBlock):
    """
    Intended as parent class for blocks with align option.
    """

    align = blocks.ChoiceBlock(
        ALIGN_CHOICES, label="zarovnání", default=LEFT, widget=forms.RadioSelect
    )

    def get_context(self, value, parent_context=None):
        context = super().get_context(value, parent_context=parent_context)
        if "css_class" not in context:
            context["css_class"] = []
        context["css_class"] += ALIGN_CSS[value["align"]]
        return context


class ColumnsTextBlock(blocks.StructBlock):
    left_text = blocks.RichTextBlock(label="levý sloupec", features=RICH_TEXT_FEATURES)
    right_text = blocks.RichTextBlock(
        label="pravý sloupec", features=RICH_TEXT_FEATURES
    )

    class Meta:
        label = "text dva sloupce"
        icon = "doc-full"
        group = "texty"
        template = "uniweb/blocks/text_columns.html"


class AdvancedColumnsTextBlock(ColorBlock, AlignBlock):
    left_text = blocks.RichTextBlock(label="levý sloupec", features=RICH_TEXT_FEATURES)
    right_text = blocks.RichTextBlock(
        label="pravý sloupec", features=RICH_TEXT_FEATURES
    )

    class Meta:
        label = "text dva sloupce (pokročilý)"
        icon = "doc-full"
        group = "texty"
        template = "uniweb/blocks/advanced_text_columns.html"


class AdvancedTitleBlock(ColorBlock, AlignBlock):
    title = blocks.CharBlock(label="nadpis")

    class Meta:
        label = "nadpis (pokročilý)"
        icon = "title"
        group = "nadpisy"
        template = "uniweb/blocks/advanced_title.html"


class PictureTitleBlock(ColorBlock):
    title = blocks.CharBlock(label="nadpis")
    image = ImageChooserBlock(label="obrázek")

    class Meta:
        label = "nadpis (s obrázkem)"
        icon = "title"
        group = "nadpisy"
        template = "uniweb/blocks/picture_title.html"


class AdvancedTextBlock(ColorBlock, AlignBlock):
    text = blocks.RichTextBlock(label="text", features=RICH_TEXT_FEATURES)

    class Meta:
        label = "text (pokročilý)"
        icon = "doc-full"
        group = "texty"
        template = "uniweb/blocks/advanced_text.html"


class MenuItemBlock(blocks.StructBlock):
    name = blocks.CharBlock(label="název")
    page = blocks.PageChooserBlock(
        label="stránka",
        page_type=["uniweb.UniwebHomePage", "uniweb.UniwebFlexiblePage"],
    )

    class Meta:
        label = "stránka"


class SubpageMixin:
    """Must be used in class definition before MetadataPageMixin!"""

    @property
    def root_page(self):
        if not hasattr(self, "_root_page"):
            self._root_page = self.get_ancestors().type(UniwebHomePage).specific().get()
        return self._root_page

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


class UniwebContentMixin(models.Model):
    content = StreamField(
        [
            (
                "title",
                blocks.CharBlock(
                    label="nadpis",
                    icon="title",
                    group="nadpisy",
                    template="uniweb/blocks/title.html",
                ),
            ),
            ("advanced_title", AdvancedTitleBlock()),
            ("picture_title", PictureTitleBlock()),
            (
                "text",
                blocks.RichTextBlock(
                    label="text",
                    features=RICH_TEXT_FEATURES,
                    group="texty",
                    template="uniweb/blocks/text.html",
                ),
            ),
            ("advanced_text", AdvancedTextBlock()),
            ("text_columns", ColumnsTextBlock()),
            ("advanced_text_columns", AdvancedColumnsTextBlock()),
            (
                "gallery",
                blocks.ListBlock(
                    ImageChooserBlock(label="obrázek"),
                    label="galerie",
                    icon="image",
                    group="ostatní",
                    template="uniweb/blocks/gallery.html",
                ),
            ),
            (
                "table",
                TableBlock(
                    label="tabulka",
                    group="ostatní",
                    template="uniweb/blocks/table.html",
                ),
            ),
            (
                "jupyter",
                DocumentChooserBlock(label="Jupyter notebook", group="ostatní"),
            ),
        ],
        verbose_name="obsah stránky",
        blank=True,
    )

    class Meta:
        abstract = True


class UniwebHomePage(Page, UniwebContentMixin, MetadataPageMixin):
    ### FIELDS

    # settings
    matomo_id = models.IntegerField(
        "Matomo ID pro sledování návštěvnosti", blank=True, null=True
    )
    top_menu = StreamField(
        [("item", MenuItemBlock())],
        verbose_name="horní menu",
        blank=True,
    )

    ### PANELS

    content_panels = Page.content_panels + [
        StreamFieldPanel("content"),
    ]

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

    settings_panels = [
        FieldPanel("matomo_id"),
        StreamFieldPanel("top_menu"),
    ]

    ### RELATIONS

    subpage_types = [
        "uniweb.UniwebFlexiblePage",
    ]

    ### OTHERS

    class Meta:
        verbose_name = "Univerzální web"

    @property
    def root_page(self):
        return self


class UniwebFlexiblePage(Page, UniwebContentMixin, SubpageMixin, MetadataPageMixin):
    ### FIELDS

    ### PANELS

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

    content_panels = Page.content_panels + [
        StreamFieldPanel("content"),
    ]

    settings_panels = []

    ### RELATIONS

    parent_page_types = ["uniweb.UniwebHomePage"]
    subpage_types = []

    ### OTHERS

    class Meta:
        verbose_name = "Flexibilní stránka"