import copy

from django.utils.html import format_html
from wagtail.core import blocks
from wagtail.core.blocks import BaseStreamBlock

__all__ = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'Row', 'Col', 'make_row_col_blocks']


class h1(blocks.CharBlock):
    def render_basic(self, value, context=None):
        if value:
            return format_html('<h1 class="scrollspy">{0}</h1>', value)
        else:
            return ''


class h2(blocks.CharBlock):
    def render_basic(self, value, context=None):
        if value:
            return format_html('<h2 class="scrollspy">{0}</h2>', value)
        else:
            return ''


class h3(blocks.CharBlock):
    def render_basic(self, value, context=None):
        if value:
            return format_html('<h3 class="scrollspy">{0}</h3>', value)
        else:
            return ''


class h4(blocks.CharBlock):
    def render_basic(self, value, context=None):
        if value:
            return format_html('<h4 class="scrollspy">{0}</h4>', value)
        else:
            return ''


class h5(blocks.CharBlock):
    def render_basic(self, value, context=None):
        if value:
            return format_html('<h5 class="scrollspy">{0}</h5>', value)
        else:
            return ''


class h6(blocks.CharBlock):
    def render_basic(self, value, context=None):
        if value:
            return format_html('<h6 class="scrollspy">{0}</h6>', value)
        else:
            return ''


class CustomStreamBlock(blocks.StreamBlock):
    """
    Identical to StreamBlock, except that we override the constructor to make it save self._base_blocks and
    self._dependencies, instead of self.base_blocks and self.dependencies. This lets us replace them with @properties.
    """

    def __init__(self, local_blocks=None, **kwargs):
        self._constructor_kwargs = kwargs

        # Note, this is calling BaseStreamBlock's super __init__, not FeatureCustomizedStreamBlock's. We don't want
        # BaseStreamBlock.__init__() to run, because it tries to assign to self.child_blocks, which it can't do because
        # we've overriden it with an @property. But we DO want Block.__init__() to run.
        super(BaseStreamBlock, self).__init__(**kwargs)

        # create a local (shallow) copy of base_blocks so that it can be supplemented by local_blocks
        self._child_blocks = self.base_blocks.copy()
        if local_blocks:
            for name, block in local_blocks:
                block.set_name(name)
                self._child_blocks[name] = block

        self._dependencies = self._child_blocks.values()

        # Additional blocks with circular dependencies
        self.additional_blocks = {}

    @property
    def child_blocks(self):
        blocks = {}
        blocks.update(self._child_blocks)
        blocks.update(self.additional_blocks)
        return blocks

    @property
    def dependencies(self):
        blocks = {}
        blocks.update(self._child_blocks)
        blocks.update(self.additional_blocks)
        return blocks

    def _check_name(self, **kwargs):
        """
        Helper method called by container blocks as part of the system checks framework,
        to validate that this block's name is a valid identifier.
        (Not called universally, because not all blocks need names)
        """
        errors = []
        return errors


class Row(CustomStreamBlock):
    """Row ('div' tags)

    See Also:
        make_row_col_blocks
    """
    def __init__(self, local_blocks=None, col_block=None, **kwargs):
        if local_blocks is None and col_block:
            local_blocks = col_block.child_blocks.copy()
        super().__init__(local_blocks, **kwargs)

        if col_block:
            self.additional_blocks['col'] = col_block
            try:
                col_block.additional_blocks['row'] = self
            except AttributeError:
                pass

    class Meta:
        template = 'wagtail_materializecss/grid/row.html'


class Col(blocks.StreamBlock):
    """Col ('div' tags)

    See Also:
        make_row_col_blocks
    """
    small = blocks.IntegerBlock(required=False, blank=True)
    medium = blocks.IntegerBlock(required=False, blank=True)
    large = blocks.IntegerBlock(required=False, blank=True)
    xl = blocks.IntegerBlock(required=False, blank=True)

    content = blocks.StreamBlock()

    class Meta:
        template = 'wagtail_materializecss/grid/col.html'


def make_row_col_blocks(local_blocks=None):
    """This function returns a list of StreamBlock arguments with row and col. Because row and col can be inside of
    each other there is a problem with cyclic dependencies."""
    col = Col(local_blocks)
    row = Row(local_blocks, col_block=col)

    return [('row', row), ('col', col)]

import copy

from django.utils.html import format_html
from wagtail.core import blocks
from wagtail.core.blocks import BaseStreamBlock

__all__ = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'Row', 'Col', 'make_row_col_blocks']


class h1(blocks.CharBlock):
    def render_basic(self, value, context=None):
        if value:
            return format_html('<h1 class="scrollspy">{0}</h1>', value)
        else:
            return ''


class h2(blocks.CharBlock):
    def render_basic(self, value, context=None):
        if value:
            return format_html('<h2 class="scrollspy">{0}</h2>', value)
        else:
            return ''


class h3(blocks.CharBlock):
    def render_basic(self, value, context=None):
        if value:
            return format_html('<h3 class="scrollspy">{0}</h3>', value)
        else:
            return ''


class h4(blocks.CharBlock):
    def render_basic(self, value, context=None):
        if value:
            return format_html('<h4 class="scrollspy">{0}</h4>', value)
        else:
            return ''


class h5(blocks.CharBlock):
    def render_basic(self, value, context=None):
        if value:
            return format_html('<h5 class="scrollspy">{0}</h5>', value)
        else:
            return ''


class h6(blocks.CharBlock):
    def render_basic(self, value, context=None):
        if value:
            return format_html('<h6 class="scrollspy">{0}</h6>', value)
        else:
            return ''


class CustomStreamBlock(blocks.StreamBlock):
    """
    Identical to StreamBlock, except that we override the constructor to make it save self._base_blocks and
    self._dependencies, instead of self.base_blocks and self.dependencies. This lets us replace them with @properties.
    """

    def __init__(self, local_blocks=None, **kwargs):
        self._constructor_kwargs = kwargs

        # Note, this is calling BaseStreamBlock's super __init__, not FeatureCustomizedStreamBlock's. We don't want
        # BaseStreamBlock.__init__() to run, because it tries to assign to self.child_blocks, which it can't do because
        # we've overriden it with an @property. But we DO want Block.__init__() to run.
        super(BaseStreamBlock, self).__init__(**kwargs)

        # create a local (shallow) copy of base_blocks so that it can be supplemented by local_blocks
        self._child_blocks = self.base_blocks.copy()
        if local_blocks:
            for name, block in local_blocks:
                block.set_name(name)
                self._child_blocks[name] = block

        self._dependencies = self._child_blocks.values()

        # Additional blocks with circular dependencies
        self.additional_blocks = {}

    @property
    def child_blocks(self):
        blocks = {}
        blocks.update(self._child_blocks)
        blocks.update(self.additional_blocks)
        return blocks

    @property
    def dependencies(self):
        blocks = {}
        blocks.update(self._child_blocks)
        blocks.update(self.additional_blocks)
        return blocks

    def _check_name(self, **kwargs):
        """
        Helper method called by container blocks as part of the system checks framework,
        to validate that this block's name is a valid identifier.
        (Not called universally, because not all blocks need names)
        """
        errors = []
        return errors


class Row(CustomStreamBlock):
    """Row ('div' tags)

    See Also:
        make_row_col_blocks
    """
    def __init__(self, local_blocks=None, col_block=None, **kwargs):
        if local_blocks is None and col_block:
            local_blocks = col_block.child_blocks.copy()
        super().__init__(local_blocks, **kwargs)

        if col_block:
            self.additional_blocks['col'] = col_block
            try:
                col_block.additional_blocks['row'] = self
            except AttributeError:
                pass

    class Meta:
        template = 'wagtail_materializecss/grid/row.html'


class Col(blocks.StreamBlock):
    """Col ('div' tags)

    See Also:
        make_row_col_blocks
    """
    small = blocks.IntegerBlock(required=False, blank=True)
    medium = blocks.IntegerBlock(required=False, blank=True)
    large = blocks.IntegerBlock(required=False, blank=True)
    xl = blocks.IntegerBlock(required=False, blank=True)

    content = blocks.StreamBlock()

    class Meta:
        template = 'wagtail_materializecss/grid/col.html'


def make_row_col_blocks(local_blocks=None):
    """This function returns a list of StreamBlock arguments with row and col. Because row and col can be inside of
    each other there is a problem with cyclic dependencies."""
    col = Col(local_blocks)
    row = Row(local_blocks, col_block=col)

    return [('row', row), ('col', col)]

Identical to StreamBlock, except that we override the constructor to make it save self._base_blocks and     self._dependencies, instead of self.base_blocks and self.dependencies. This lets us replace them with @properties. # Note, this is calling BaseStreamBlock's super __init__, not FeatureCustomizedStreamBlock's. We don't want # BaseStreamBlock.__init__() to run, because it tries to assign to self.child_blocks, which it can't do because # we've overriden it with an @property. But we DO want Block.__init__() to run. # create a local (shallow) copy of base_blocks so that it can be supplemented by local_blocks # Additional blocks with circular dependencies Helper method called by container blocks as part of the system checks framework,         to validate that this block's name is a valid identifier.         (Not called universally, because not all blocks need names) Row ('div' tags)      See Also:         make_row_col_blocks Col ('div' tags)      See Also:         make_row_col_blocks This function returns a list of StreamBlock arguments with row and col. Because row and col can be inside of     each other there is a problem with cyclic dependencies.