class Card(object):

    """
    Card is a class that generates a Propeller Card.

    **Parameters**:

        primary_title
            An instance of CardTitle. Optional.

        secondary_title
            An instance of CardSubtitle. Optional.

        header
            An instance of CardHeader. Optional.

        media
            An instance of CardMedia. Optional.

        body
            An instance of CardBody. Optional.

        actions
            An instance of CardActions. Optional.

        media_actions
            An instance of CardMediaActions. Optional.

        style_inverse
            Display dark style if true. (Default: False)

        style_inline
            Display card with inline style if true. (Default: False)

        width
            Width of the card in Bootstrap grid (col-md) as integer. (Default: 4)
    """

    primary_title = None
    secondary_title = None
    header = None
    media = None
    body = None
    actions = None
    media_actions = None
    style_inverse = False
    style_inline = False
    width = 4

    def get_actions(self):
        """Returns actions of card as html"""
        actions = ''
        if self.media_actions:
            actions = text_concat(actions, self.media_actions.as_html())
        if self.actions:
            actions = text_concat(actions, self.actions.as_html())
        return actions

    def get_content(self):
        """Returns content of card as html"""
        content = ''
        if self.header and not self.style_inline:
            content = text_concat(content, self.header.as_html())
        if self.media:
            content = text_concat(content, self.media.as_html())
        if not self.style_inline:
            if self.primary_title or self.secondary_title:
                content = text_concat(content, '<div class="pmd-card-title">')
                if self.primary_title:
                    content = text_concat(content, self.primary_title.as_html())
                if self.secondary_title:
                    content = text_concat(content, self.secondary_title.as_html())
                content = text_concat(content, '</div>')
            if self.body:
                content = text_concat(content, self.body.as_html())
        content = text_concat(content, self.get_actions())
        return content

    def as_html(self):
        """Returns card as html"""
        tag = 'div'
        classes = 'pmd-card'
        if self.style_inline:
            classes = add_css_class(classes, 'pmd-card-media-inline')
        if self.style_inverse:
            classes = add_css_class(classes, 'pmd-card-inverse')
        else:
            classes = add_css_class(classes, 'pmd-card-default')
        classes = add_css_class(classes, 'pmd-z-depth')
        classes = add_css_class(classes, 'col-md-%d' % self.width)
        attrs = {'class': classes}
        content = self.get_content()
        return render_tag(tag, attrs=attrs, content=mark_safe(content), ) class CardHeader(object):

    """
    Renders a Card Header.

    **Parameters**:

        content_left
            A list of items to display on the left of header. 
            May contain Button, FAB, Image, CardTitle, or CardSubtitle.

        content_middle
            A list of items to display in the middle of header. 
            May contain Button, FAB, Image, CardTitle, or CardSubtitle.
    """

    content_left = []
    content_middle = []

    def get_left_content(self):
        """Returns left content of card header as html"""
        tag = 'div'
        attrs = {'class': 'media-left'}
        content = ''
        for itm in self.content_left:
            content = text_concat(content, mark_safe(itm.as_html()))
        return render_tag(tag, attrs=attrs, content=mark_safe(content), )

    def get_middle_content(self):
        """Returns middle content of card header as html"""
        tag = 'div'
        attrs = {'class': 'media-body media-middle'}
        content = ''
        for itm in self.content_middle:
            content = text_concat(content, mark_safe(itm.as_html()))
        return render_tag(tag, attrs=attrs, content=mark_safe(content), )

    def as_html(self):
        """Returns card header as html"""
        tag = 'div'
        attrs = {'class': 'pmd-card-title'}
        content = text_concat(self.get_left_content(), self.get_middle_content())
        return render_tag(tag, attrs=attrs, content=mark_safe(content), ) class CardActions(object):

    """
    Renders Card Actions.

    **Parameters**:

        items
            A list of items to display in the Card Action section. 
            May contain Button or FAB.
    """

    items = []

    def as_html(self):
        """Returns card actions as html"""
        tag = 'div'
        attrs = {'class': 'pmd-card-actions'}
        content = ''
        for btn in self.items:
            if isinstance(btn, Button):
                content = text_concat(content, mark_safe(btn.as_html()))
        return render_tag(tag, attrs=attrs, content=mark_safe(content), ) class CardMediaActions(object):

    """
    Renders Card Media Actions.

    **Parameters**:

        items
            A list of items to display in the Card Media Action section. 
            May contain Button or FAB.
    """

    items = []

    def as_html(self):
        """Returns card media actions as html"""
        tag = 'div'
        attrs = {'class': 'pmd-card-actions'}
        content = ''
        for btn in self.items:
            if isinstance(btn, FAB):
                content = text_concat(content, mark_safe(btn.as_html()))
        return render_tag(tag, attrs=attrs, content=mark_safe(content), ) class CardTitle(object):

    """
    Renders a Card Title.

    **Parameters**:

        text
            The display text for the title.

        size
            The size for the title as integer. Works with the h-tag, so size=1 is bigger than size=3.
            Optional. (default=3)
    """

    text = ""
    size = 3

    def as_html(self):
        """Returns card title as html"""
        tag = 'h%d' % self.size
        attrs = {'class': 'pmd-card-title-text'}
        content = self.text
        return render_tag(tag, attrs=attrs, content=mark_safe(content), ) class CardSubtitle(object):

    """
    Renders a Card Subtitle.

    **Parameters**:

        text
            The display text for the subtitle.
    """

    text = ""

    def as_html(self):
        """Returns card subtitle as html"""
        tag = 'span'
        attrs = {'class': 'pmd-card-subtitle-text'}
        content = self.text
        return render_tag(tag, attrs=attrs, content=mark_safe(content), ) class CardMediaImage(object):

    """
    Renders a Card Media Image.

    **Parameters**:

        image
            Must be an instance of an Image.
    """

    image = None

    def as_html(self):
        """Returns card media image as html"""
        if isinstance(self.image, Image):
            return self.image.as_html()
        return None class CardBody(object):

    """
    Renders a Card Body.

    **Parameters**:

        text
            The text to display in the body.
    """

    text = ""

    def as_html(self):
        """Returns card body as html"""
        tag = 'div'
        attrs = {'class': 'pmd-card-body'}
        content = self.text
        return render_tag(tag, attrs=attrs, content=mark_safe(content), ) class CardMedia(object):

    """
    Renders Card Media

    **Parameters**:

        content
            if style_inline=True:
                A list of items to display in the card media section. 
                May contain CardMediaImage, CardTitle, or CardSubtitle.
            or if style_inline=False: (default)
                A instance of CardMediaImage

        style_inline
            Display card with inline style if true. (Default: False)
    """

    content = None
    style_inline = False

    def get_media_body_inline(self):
        """Returns media body inline as html"""
        tag = 'div'
        attrs = {'class': 'media-body'}
        content = ''
        if self.style_inline:
            if not isinstance(self.content, list):
                raise PropellerException("Propeller Card: content must be a list")
            for itm in self.content:
                if isinstance(itm, (CardTitle, CardSubtitle)):
                    content = text_concat(content, mark_safe(itm.as_html()))
            content = text_concat(content, mark_safe('</div>'))
            content = text_concat(content, mark_safe('<div class="media-right media-middle">'))
            for itm in self.content:
                if isinstance(itm, CardMediaImage):
                    content = text_concat(content, mark_safe(itm.as_html()))
        return render_tag(tag, attrs=attrs, content=mark_safe(content), )

    def get_media_body(self):
        """Returns media body as html"""
        if self.style_inline:
            return self.get_media_body_inline()

        tag = 'div'
        attrs = {'class': 'media-body'}
        content = ''
        if not isinstance(self.content, list):
            raise PropellerException("Propeller Card: content must be a list")
        for itm in self.content:
            if isinstance(itm, CardMediaImage):
                content = text_concat(content, mark_safe(itm.as_html()))

        return render_tag(tag, attrs=attrs, content=mark_safe(content), )

    def as_html(self):
        """Returns card media as html"""
        tag = 'div'
        attrs = {'class': 'pmd-card-media'}
        content = self.get_media_body()
        return render_tag(tag, attrs=attrs, content=mark_safe(content), ) class Image(object):

    """Render an image object"""

    source = ""
    link = None
    width = None
    height = None
    responsive = False
    avatar = False

    def __init__(self, source="", link=None, width=None, height=None, responsive=False, avatar=False):
        self.source = source
        self.link = link
        self.width = width
        self.height = height
        self.responsive = responsive
        self.avatar = avatar

    def as_html(self):
        img_str = ''
        if self.link:
            img_str += '<a'
            if self.avatar:
                img_str += ' class="avatar-list-img"'
            img_str += '>'
        img_str += '<img src="%s"' % self.source
        if self.width:
            img_str += ' width="%d"' % int(self.width)
        if self.height:
            img_str += ' height="%d"' % int(self.height)
        if self.responsive:
            img_str += ' class="img-responsive"'
        img_str += '>'
        if self.link:
            img_str += '</a>'
        return img_str class Button(object):

    """Render a button with content"""

    attrs = {}
    content = ""
    classes = []

    def __init__(self, content, button_type='button', icon=None, button_class=None, size=None,
                 href=None, name=None, value=None, title=None, style='default', extra_classes='', _id=''):
        pmd_class = 'pmd-ripple-effect'
        if not button_class:
            button_class = 'btn-default'
        self.classes = add_css_class('btn', button_class)
        self.classes = add_css_class(self.classes, pmd_class)
        size = text_value(size).lower().strip()
        self.content = content
        if size == 'xs':
            self.classes = add_css_class(self.classes, 'btn-xs')
        elif size == 'sm' or size == 'small':
            self.classes = add_css_class(self.classes, 'btn-sm')
        elif size == 'lg' or size == 'large':
            self.classes = add_css_class(self.classes, 'btn-lg')
        elif size == 'md' or size == 'medium':
            pass
        elif size:
            raise PropellerError(
                'Parameter "size" should be "xs", "sm", "lg" or ' +
                'empty ("{}" given).'.format(size))
        if button_type:
            if button_type not in ('submit', 'reset', 'button', 'link'):
                raise PropellerError(
                    'Parameter "button_type" should be "submit", "reset", ' +
                    '"button", "link" or empty  ("{}" given).'.format(button_type))
            self.attrs['type'] = button_type
        if style not in ('default', 'raised', 'flat', 'outline'):
            raise PropellerError(
                'Parameter "style" should be "default", "raised", ' +
                '"flat", "outline" or empty  ("{}" given).'.format(style))
        else:
            self.classes = add_css_class(self.classes, 'pmd-btn-%s' % style)
            self.classes = add_css_class(self.classes, extra_classes)
        self.icon_content = render_icon(icon) if icon else ''
        if href:
            self.attrs['href'] = href
            self.tag = 'a'
        else:
            self.tag = 'button'
        if _id:
            self.attrs['id'] = _id
        if name:
            self.attrs['name'] = name
        if value:
            self.attrs['value'] = value
        if title:
            self.attrs['title'] = title

    def as_html(self):
        self.attrs['class'] = self.classes
        return render_tag(self.tag, attrs=self.attrs,
                          content=mark_safe(text_concat(self.icon_content, self.content, separator=' ')), ) class FAB(object):

    """Render a floating action button"""

    attrs = {}
    content = ""
    classes = []

    def __init__(self, content, button_type='button', icon=None, button_class=None, size=None,
                 href=None, name=None, value=None, title=None, style='default', extra_classes='', _id=''):
        pmd_class = 'pmd-ripple-effect'
        if not button_class:
            button_class = 'btn-default'
        self.classes = add_css_class('', 'btn')
        size = text_value(size).lower().strip()
        self.content = content
        if size == 'xs':
            self.classes = add_css_class(self.classes, 'btn-xs')
        elif size == 'sm' or size == 'small':
            self.classes = add_css_class(self.classes, 'btn-sm')
        elif size == 'lg' or size == 'large':
            self.classes = add_css_class(self.classes, 'btn-lg')
        elif size == 'md' or size == 'medium':
            pass
        elif size:
            raise PropellerError(
                'Parameter "size" should be "xs", "sm", "lg" or ' +
                'empty ("{}" given).'.format(size))
        self.classes = add_css_class(self.classes, 'pmd-btn-fab')
        if button_type:
            if button_type not in ('submit', 'reset', 'button', 'link'):
                raise PropellerError(
                    'Parameter "button_type" should be "submit", "reset", ' +
                    '"button", "link" or empty  ("{}" given).'.format(button_type))
            self.attrs['type'] = button_type
        if style not in ('default', 'raised', 'flat', 'outline'):
            raise PropellerError(
                'Parameter "style" should be "default", "raised", ' +
                '"flat", "outline" or empty  ("{}" given).'.format(style))
        else:
            self.classes = add_css_class(self.classes, 'pmd-btn-%s' % style)
        self.classes = add_css_class(self.classes, pmd_class)
        self.classes = add_css_class(self.classes, extra_classes)
        self.icon_content = render_icon(icon) if icon else ''
        if href:
            self.attrs['href'] = href
            self.tag = 'a'
        else:
            self.tag = 'button'
        if _id:
            self.attrs['id'] = _id
        if name:
            self.attrs['name'] = name
        if value:
            self.attrs['value'] = value
        if title:
            self.attrs['title'] = title
        self.classes = add_css_class(self.classes, button_class)

    def as_html(self):
        self.attrs['class'] = self.classes
        return render_tag(self.tag, attrs=self.attrs,
                          content=mark_safe(text_concat(self.icon_content, self.content, separator=' ')), )
from django_propeller.card import Card, CardHeader, CardActions, CardMediaActions, CardTitle, CardSubtitle, \
    CardMediaImage, CardBody, CardMedia
from django_propeller.components import Image, Button, FAB


class DemoTitle1(CardTitle):
    text = "Title goes here"
    size = 2


class DemoHeaderTitle1(CardTitle):
    text = "Two-line item"
    size = 3


class DemoSubtitle1(CardSubtitle):
    text = "Secondary text"


class DemoMediaImage1(CardMediaImage):
    image = Image(source="http://propeller.in/assets/images/profile-pic.png", responsive=True)


class DemoMediaImage2(CardMediaImage):
    image = Image(source="http://propeller.in/assets/images/profile-pic.png", width=80, height=80)


class DemoMedia1(CardMedia):
    content = [DemoMediaImage1(), ]


class DemoMedia2(CardMedia):
    content = [DemoTitle1(), DemoSubtitle1(), DemoMediaImage2(), ]


class DemoBody1(CardBody):
    text = "Cards provide context and an entry point to more robust information and views. " \
           "Don't overload cards with extraneous information or actions."


class DemoHeader1(CardHeader):
    content_middle = [DemoHeaderTitle1(), DemoSubtitle1()]
    content_left = [Image("http://propeller.in/assets/images/avatar-icon-40x40.png", width=40, height=40, avatar=True)]


class DemoActions1(CardActions):
    items = [
        Button(content='primary', button_class='btn-primary'),
        Button('Action'),
        Button('third')
    ]


class DemoMediaActions1(CardMediaActions):
    items = [
        FAB('', button_class='btn-primary', icon='share', style='flat', size='sm'),
        FAB('', button_class='btn-primary', icon='thumb_up', style='flat', size='sm'),
        FAB('', button_class='btn-primary', icon='drafts', style='flat', size='sm')
    ]



class DemoCard1(Card):