#------------------------------------------------------------------------------
#  Copyright (c) 2012, Enthought, Inc.
#  All rights reserved.
#------------------------------------------------------------------------------
from traits.api import Instance, Str

from enaml.layout.constraint_variable import ConstraintVariable
from enaml.layout.layout_helpers import align, hbox, vbox

from .container import  Container


class Form(Container):
    """ A Container subclass that arranges its children in two columns.

    The left column is typically Labels (but this is not a requirement).
    The right are the actual widgets for data entry. The children should
    be in alternating label/widget order. If there are an odd number
    of children, the last child will span both columns.

    The Form provides an extra constraint variable, 'midline', which
    is used as the alignment anchor for the columns.

    """
    #: The ConstraintVariable giving the midline along which the labels
    #: and widgets are aligned.
    midline = Instance(ConstraintVariable)
    def _midline_default(self):
        return ConstraintVariable('midline', self.object_id)

    #: The strength for the form layout constraints.
    # FIXME: Use an Enum.
    layout_strength = Str('strong')

    #: A form hugs its height strongly by default. Forms are typcially
    #: used to display vertical arrangements of widgets, with forms
    #: often being stacked on top of each other. For this case, hugging
    #: the height is desired.
    hug_height = 'strong'

    def _component_constraints(self):
        """ Supplies the constraints which layout the children in a
        two column form.

        """
        # FIXME: do something sensible when children are not visible.
        children = list(self.widgets)
        labels = children[::2]
        widgets = children[1::2]

        n_labels = len(labels)
        n_widgets = len(widgets)

        if n_labels != n_widgets:
            if n_labels > n_widgets:
                odd_child = labels.pop()
            else:
                odd_child = widgets.pop()
        else:
            odd_child = None

        layout_strength = self.layout_strength
        constraints = []

        # Align the left side of each widget with the midline constraint
        # variable of the form.
        midline = self.midline
        for widget in widgets:
            cn = (widget.left == midline) | layout_strength
            constraints.append(cn)

        # Arrange each label/widget pair horizontally in the form
        # XXX this is a highly inefficient way to generate these
        # constraints. It starts to be noticeably slow when the
        # form has around 20 rows. This can be done better.
        labels_widgets = zip(labels, widgets)
        vbox_args = [hbox(label, widget) for label, widget in labels_widgets]
        if odd_child is not None:
            vbox_args.append(odd_child)
        constraints.append(vbox(*vbox_args))

        for label, widget in labels_widgets:
            # FIXME: baselines would be much better.
            constraints.append(align('v_center', label, widget) | layout_strength)

        return constraints

    def _default_constraints(self):
        """ Overridden parent class method which returns an empty list.

        This disables the vbox constraints supplied by the superclass
        Container. All Form constraints are generated by the
        '_component_constraints' method.

        """
        return []

