

"""Contains widgets for radio forms"""


from .. import tag
from . import Widget, ClosedWidget, FieldArg, FieldArgList, FieldArgTable, FieldArgDict



class RadioButton1(Widget):
    """A radiobutton widget. Without a form or submit button, typically included within a form"""

    error_location = (0,0,0)

    arg_descriptions = {'radio_values':FieldArgList("text"),
                       'radio_text':FieldArgList("text"),
                       'radio_checked':FieldArg("text", '', valdt=True, jsonset=True),
                       'error_class':FieldArg("cssclass", ""),
                       'inputdiv_class':FieldArg("cssclass", ""),
                       'label_class':FieldArg("cssclass", ""),
                       'div_class':FieldArg("cssclass", "")
                       }

    def __init__(self, name=None, brief='', **field_args):
        """
        radio_values: list of options, one of these values will be returned
        radio_text: List of labels
        radio_checked: value to be checked, this is the field returned
        show: True if this widget is to be visible
        error_class: css class applied to the normally hidden error div
        inputdiv_class: css class applied to each radio div
        label_class: css class applied to each label text on the right of the radio button
        div_class: css class applied to the div after the error paragraph
        """
        Widget.__init__(self, name=name, brief=brief, **field_args)
        self.tag_name = "div"
        # hidden error
        self[0] = tag.Part(tag_name="div", attribs={"style":"display:none;"})
        self[0][0] = tag.Part(tag_name="p")
        self[0][0][0] = ''
        self[1] = tag.Part(tag_name="div")


    def _build(self, page, ident_list, environ, call_data, lang):
        "Build the radio buttons"

        if self.wf.error_class:
            self[0].attribs["class"] = self.wf.error_class
        if self.error_status:
            del self[0].attrib["style"]
        if self.wf.div_class:
            self[1].attribs["class"] = self.wf.div_class
        checked = self.wf.radio_checked
        name = self.get_formname('radio_checked')
        label_class = self.wf.label_class
        one_id = self[1].insert_id()
        for index,val in enumerate(self.wf.radio_values):
            if self.wf.inputdiv_class:
                inputblock = tag.Part(tag_name="div", attribs={"class":self.wf.inputdiv_class})
            else:
                inputblock = tag.Part(tag_name="div")
            if checked and (checked == val):
                inputblock[0] = tag.ClosedPart(tag_name="input",
                                            attribs ={"name":name,
                                                      "value":val,
                                                      "checked":"checked",
                                                      "type":"radio"})
                # ensure only one item checked
                checked = ''
            else:
                inputblock[0] = tag.ClosedPart(tag_name="input",
                                            attribs ={"name":name,
                                                      "value":val,
                                                      "type":"radio"})
            ibid = inputblock[0].insert_id(one_id + '_' + str(index) + '_0')
            if label_class:
                inputblock[1] = tag.Part(tag_name="label", attribs = {"class": label_class, 'for':ibid})
            else:
                inputblock[1] = tag.Part(tag_name="label", attribs = {'for':ibid})

            try:
                inputblock[1][0] = self.wf.radio_text[index]
            except IndexError:
                inputblock[1][0] = ''
            self[1].append(inputblock)


    @classmethod
    def description(cls):
        """Returns a text string to illustrate the widget"""
        return """<div>  <!-- with widget id and class widget_class -->
  <div> <!-- normally hidden div, with class error_class -->
    <p> <!-- Any error text appears here --> </p>
  </div>
  <div>  <!-- with class attribute set to div_class if a class is set -->
    <!-- Then for each radio field -->
    <div> <!-- with class set to inputdiv_class if a class is set -->
      <input type='radio' /> <!-- with name from 'radio_checked' widgfield and values from radio_values -->
      <label> <!-- with class set to label_class and content from radio_text -->
      </label>
    </div>
  </div>
</div>
"""


class RadioTable(Widget):
    """A div containing a table of radio controls with textblocks. Without a form or submit button, typically included within a form

       The first colum is the radio control with its associated label, the second column is either a textblock, or (if given)
       a string of text"""

    error_location = (0,0,0)

    arg_descriptions = {'table_class':FieldArg("cssclass", ''),
                        'header_class':FieldArg("cssclass", ''),
                        'even_class':FieldArg("cssclass", ''),
                        'odd_class':FieldArg("cssclass", ''),
                        'error_class':FieldArg("cssclass", ''),
                        'title1':FieldArg("text"),
                        'title2':FieldArg("text"),
                        'radio_checked':FieldArg("text", valdt=True),
                        'contents':FieldArgTable(['text', 'text', 'textblock_ref', 'text'])
                       }

    def __init__(self, name=None, brief='', **field_args):
        """
        table_class: class of the table, if empty string, then no class will be applied
        header_class: class of the header row, if empty string, then no class will be applied
        even_class: class of even rows, if empty string, then no class will be applied
        odd_class: class of odd rows, if empty string, then no class will be applied
        error_class: css class applied to the normally hidden error paragraph
        title1: The header title over the first column
        title2: The header title over the second column
        radio_checked: value to be checked, this is the field returned
        contents: table of values, labels and textblock or text
        """
        Widget.__init__(self, name=name, brief=brief, **field_args)
        self.tag_name = "div"
        # hidden error
        self[0] = tag.Part(tag_name="div", attribs={"style":"display:none;"})
        self[0][0] = tag.Part(tag_name="p")
        self[0][0][0] = ''
        self[1] = tag.Part(tag_name='table')


    def _build(self, page, ident_list, environ, call_data, lang):
        "Build the table of radio buttons"
        if self.wf.error_class:
            self[0].attribs["class"] = self.wf.error_class
        if self.error_status:
            del self[0].attribs["style"]

        checked = self.wf.radio_checked
        name = self.get_formname('radio_checked')
        fieldtable = self.wf.contents
        if self.wf.table_class:
            self[1].attribs["class"] = self.wf.table_class
        # set table header with titles
        header = 0
        if self.wf.title1 or self.wf.title2:
            header = 1
            if self.wf.header_class:
                self[1][0] = tag.Part(tag_name='tr', attribs={"class":self.wf.header_class})
            else:
                self[1][0] = tag.Part(tag_name='tr')
            self[1][0][0] = tag.Part(tag_name='th', text = self.wf.title1)
            self[1][0][1] = tag.Part(tag_name='th', text = self.wf.title2)
        # set even row colour
        if self.wf.even_class:
            even = self.wf.even_class
        else:
            even = ''
        # set odd row colour
        if self.wf.odd_class:
            odd = self.wf.odd_class
        else:
            odd = ''

        for index,val in enumerate(fieldtable):
            rownumber = index+header
            if even and (rownumber % 2) :
                self[1][rownumber] = tag.Part(tag_name="tr", attribs={"class":even})
            elif odd and not (rownumber % 2):
                self[1][rownumber] = tag.Part(tag_name='tr', attribs={"class":odd})
            else:
                self[1][rownumber] = tag.Part(tag_name='tr')
            # first col
            col0 = tag.Part(tag_name='td')
            if checked and (checked == val[0]):
                input_prt = tag.ClosedPart(tag_name="input",
                                            attribs ={"name":name,
                                                      "value":val[0],
                                                      "checked":"checked",
                                                      "type":"radio"})
                # ensure only one item checked
                checked = ''
            else:
                input_prt = tag.ClosedPart(tag_name="input",
                                            attribs ={"name":name,
                                                      "value":val[0],
                                                      "type":"radio"})
            input_label = tag.Part(tag_name='label')
            input_label[0] = input_prt
            input_label[1] = val[1]
            col0[0] = input_label
            # second col
            col1 = tag.Part(tag_name='td')
            if val[3]:
                # if text is given, this is set into the column
                col1[0] = val[3]
            else:
                # if no text, then the texblock is set
                col1[0] = val[2]
            # add the two columns to the row
            self[1][rownumber][0] = col0
            self[1][rownumber][1] = col1


    @classmethod
    def description(cls):
        """Returns a text string to illustrate the widget"""
        return """
<div>  <!-- with widget id and class widget_class -->
  <div> <!-- normally hidden paragraph, with class error_class -->
    <p> <!-- Any error text appears here --> </p>
  </div>
  <table>  <!-- with CSS class given by table_class -->
    <tr> <!-- with header class -->
      <th> <!-- title1 --> </th>
      <th> <!-- title2 --> </th>
    </tr>
    <!-- Then the following row repeated for each row given in the contents field -->
    <tr> <!-- with class  from even or odd classes -->
      <td>
        <label>
          <input type="radio" />
          <!-- with name from name of radio_checked field, and value from the contents -->
          <!-- label text from contents -->
        </label>
      </td>
      <td> <!-- textblock, found from row textbock_ref --> </td>
    </tr>
    <!-- rows repeated -->
  </table>
</div>"""
            


class TwoRadioOptions(Widget):
    """A two option radio control. Without a form or submit button, typically included within a form
       label appeares to the right of the buttons
        """
    # This class does not display any error messages
    display_errors = False

    arg_descriptions = {'label1':FieldArg("text"),
                        'div_class1':FieldArg("cssclass", ''),
                        'value1':FieldArg("text"),
                        'label2':FieldArg("text"),
                        'div_class2':FieldArg("cssclass", ''),
                        'value2':FieldArg("text"),
                        'radio_checked':FieldArg("text", valdt=True)
                       }

    def __init__(self, name=None, brief='', **field_args):
        """
        div_class1: css class of div containing first radio box
        label1: text label to appear after the first radio button
        value1: the value returned if the first radio button is chosen
        div_class2: css class of div containing second radio box
        label2: text label to appear after the second radio button
        value2: the value returned if the second radio button is chosen
        radio_checked: value to be checked, this is the field returned
        """
        Widget.__init__(self, name=name, brief=brief, **field_args)
        self.tag_name = "div"
        self[0] = tag.Part(tag_name='div')
        self[0][0] = tag.Part(tag_name='label')
        self[1] = tag.Part(tag_name='div')
        self[1][0] = tag.Part(tag_name='label')


    def _build(self, page, ident_list, environ, call_data, lang):
        "Build the radio buttons"
        checked = self.wf.radio_checked
        name = self.get_formname('radio_checked')

        if self.wf.div_class1:
            self[0].attribs["class"] = self.wf.div_class1
        if self.wf.div_class2:
            self[1].attribs["class"] = self.wf.div_class2

        if checked and (checked == self.wf.value1):
            self[0][0][0] = tag.ClosedPart(tag_name="input",
                                     attribs ={"name":name,
                                     "value":self.wf.value1,
                                     "checked":"checked",
                                     "type":"radio"})
        else:
            self[0][0][0] = tag.ClosedPart(tag_name="input",
                                     attribs ={"name":name,
                                     "value":self.wf.value1,
                                     "type":"radio"})
        self[0][0][1] = self.wf.label1
        if checked and (checked == self.wf.value2):
            self[1][0][0] = tag.ClosedPart(tag_name="input",
                                     attribs ={"name":name,
                                     "value":self.wf.value2,
                                     "checked":"checked",
                                     "type":"radio"})
        else:
            self[1][0][0] = tag.ClosedPart(tag_name="input",
                                     attribs ={"name":name,
                                     "value":self.wf.value2,
                                     "type":"radio"})
        self[1][0][1] = self.wf.label2


    @classmethod
    def description(cls):
        """Returns a text string to illustrate the widget"""
        return """
<div>  <!-- with widget id and class widget_class -->
  <div>  <!-- with class attribute set to div_class1 if a class is set -->
    <label>
      <input type='radio' /> <!-- with name from 'radio_checked' widgfield and value from value1 -->
      <!-- text from label1 -->
    </label>
  </div>
  <div>  <!-- with class attribute set to div_class2 if a class is set -->
    <label>
      <input type='radio' /> <!-- with name from 'radio_checked' widgfield and value from value2 -->
      <!-- text from label2 -->
    </label>
  </div>
</div>
"""


class BooleanRadio(Widget):
    """A two option radio control for choosing True or False. Without a form or submit button, typically included within a form."""

    # This class does not display any error messages
    display_errors = False

    arg_descriptions = {'div_class1':FieldArg("cssclass", ''),
                        'left_label1':FieldArg("text", 'True'),
                        'left_class1':FieldArg("cssclass", ''),
                        'left_style1':FieldArg("cssstyle", ''),
                        'right_label1':FieldArg("text", ''),
                        'right_class1':FieldArg("cssclass", ''),
                        'right_style1':FieldArg("cssstyle", ''),
                        'div_class2':FieldArg("cssclass", ''),
                        'left_label2':FieldArg("text", 'False'),
                        'left_class2':FieldArg("cssclass", ''),
                        'left_style2':FieldArg("cssstyle", ''),
                        'right_label2':FieldArg("text", ''),
                        'right_class2':FieldArg("cssclass", ''),
                        'right_style2':FieldArg("cssstyle", ''),
                        'radio_checked':FieldArg("boolean", True, valdt=True)
                       }

    def __init__(self, name=None, brief='', **field_args):
        """
        div_class1: class of the first div containing the first radio button
        left_label1: The text displayed to the left of the first radio button
        left_class1: The css class of the label to the left of the first radio button
        right_label1: The text displayed to the right of the first radio button
        right_class1: The css class of the label to the right of the first radio button
        div_class2: class of the second div containing the second radio button
        left_label2: The text displayed to the left of the second radio button
        left_class2: The css class of the label to the left of the second radio button
        right_label2: The text displayed to the right of the second radio button
        right_class2: The css class of the label to the right of the second radio button
        radio_checked: default value to be checked, True or False, field name is the field returned
        """
        Widget.__init__(self, name=name, brief=brief, **field_args)
        self.tag_name = "div"
        self[0] = tag.Part(tag_name='div')
        self[0][0] = tag.Part(tag_name="label", hide_if_empty=True)
        self[0][1] = tag.ClosedPart(tag_name="input")
        self[0][2] = tag.Part(tag_name="label", hide_if_empty=True)
        self[1] = tag.Part(tag_name='div')
        self[1][0] = tag.Part(tag_name="label", hide_if_empty=True)
        self[1][1] = tag.ClosedPart(tag_name="input")
        self[1][2] = tag.Part(tag_name="label", hide_if_empty=True)


    def _build(self, page, ident_list, environ, call_data, lang):
        "Build the radio buttons"
        div1 = self[0]
        div2 = self[1]

        if self.wf.div_class1:
            div1.attribs["class"] = self.wf.div_class1
        if self.wf.div_class2:
            div2.attribs["class"] = self.wf.div_class2

        # labels of first div
        div1[0].set_class_style(self.wf.left_class1, self.wf.left_style1)
        div1[0][0] = self.wf.left_label1

        div1[2].set_class_style(self.wf.right_class1, self.wf.right_style1)
        div1[2][0] = self.wf.right_label1


        # labels of second div
        div2[0].set_class_style(self.wf.left_class2, self.wf.left_style2)
        div2[0][0] = self.wf.left_label2

        div2[2].set_class_style(self.wf.right_class2, self.wf.right_style2)
        div2[2][0] = self.wf.right_label2

        name = self.get_formname('radio_checked')
        if self.wf.radio_checked:
            # True chosen
            div1[1].attribs.update({"type":"radio", 'name': name, "checked":"checked", "value":"True"})
            div2[1].attribs.update({"type":"radio", 'name': name, "value":"False"})
        else:
            # False chosen
            div1[1].attribs.update({"type":"radio", 'name': name, "value":"True"})
            div2[1].attribs.update({"type":"radio", 'name': name, "checked":"checked", "value":"False"})

        # set the label 'for' attribute to the input field id
        div1_1_id = div1[1].insert_id()
        div1[0].attribs.update({'for':div1_1_id})
        div1[2].attribs.update({'for':div1_1_id})
        div2_1_id = div2[1].insert_id()
        div2[0].attribs.update({'for':div2_1_id})
        div2[2].attribs.update({'for':div2_1_id})

    @classmethod
    def description(cls):
        """Returns a text string to illustrate the widget"""
        return """
<div>  <!-- with widget id and class widget_class -->
  <div>  <!-- with class attribute set to div_class1 if a class is set -->
      <label> <!-- with class set to left_class1 and content to left_label1 -->
      </label>
      <input type='radio' value='True' /> <!-- checked if radio_checked field is True -->
      <label> <!-- with class set to right_class1 and content to right_label1 -->
      </label>
  </div>
  <div>  <!-- with class attribute set to div_class2 if a class is set -->
      <label> <!-- with class set to left_class2 and content to left_label2 -->
      </label>
      <input type='radio' value='False' /> <!-- checked if radio_checked field is False -->
      <label> <!-- with class set to right_class2 and content to right_label2 -->
      </label>
  </div>
</div>"""



class RadioTable2(Widget):
    """A table of three columns, two being text strings, the third radio buttons
       The first row is three header titles. Typically inserted into a form
       does not display errors"""

    # This class does not display any error messages
    display_errors = False

    arg_descriptions = {'header_class':FieldArg("cssclass",""),
                        'title1':FieldArg('text', ''),
                        'title2':FieldArg('text', ''),
                        'title3':FieldArg('text', ''),
                        'row_classes':FieldArgList('text', jsonset=True),
                        'col1':FieldArgList('text', jsonset=True),
                        'col2':FieldArgList('text', jsonset=True),
                        'radiocol':FieldArgList('text'),
                        'radio_checked':FieldArg("text", valdt=True, jsonset=True)
                        }

    def __init__(self, name=None, brief='', **field_args):
        """
        header_class: class of the header row, if empty string, then no class will be applied
        title1: The header title over the first text column
        title2: The header title over the second text column
        title3: The header title over the second text column
        row_classes: A list of CSS classes to apply to each row (not including the header)
        col1: A list of text strings to place in the first column
        col2: A list of text strings to place in the second column
        radiocol: A list of value strings for the radio buttons to place in the third column
        radio_checked: value to be checked, this is the field returned
        """
        Widget.__init__(self, name=name, brief=brief, **field_args)
        self.tag_name = "table"

    def _build(self, page, ident_list, environ, call_data, lang):
        "Build the table"
        rowc = self.wf.row_classes
        col1 = self.wf.col1
        col2 = self.wf.col2
        col3 = self.wf.radiocol
        checked = self.wf.radio_checked
        name = self.get_formname('radio_checked')
        header = 0
        if self.wf.title1 or self.wf.title2 or self.wf.title3:
            header = 1
            if self.wf.header_class:
                self[0] = tag.Part(tag_name='tr', attribs={"class":self.wf.header_class})
            else:
                self[0] = tag.Part(tag_name='tr')
            self[0][0] = tag.Part(tag_name='th', text = self.wf.title1)
            self[0][1] = tag.Part(tag_name='th', text = self.wf.title2)
            self[0][2] = tag.Part(tag_name='th', text = self.wf.title3)

        # create rows
        rows = max( len(col1), len(col2), len(col3) )
        if not rowc:
            rowc = ['']*rows
        if rows > len(rowc):
            rowc.extend(['']*(rows - len(rowc)))
        if rows > len(col1):
            col1.extend(['']*(rows - len(col1)))
        if rows > len(col2):
            col2.extend(['']*(rows - len(col2)))
        if rows > len(col3):
            col3.extend([None]*(rows - len(col3)))

        for index in range(rows):
            rownumber = index+header
            if rowc[index]:
                self[rownumber] = tag.Part(tag_name='tr', attribs={"class":rowc[index]})
            else:
                self[rownumber] = tag.Part(tag_name='tr')
            self[rownumber][0] = tag.Part(tag_name='td', text = col1[index])
            self[rownumber][1] = tag.Part(tag_name='td', text = col2[index])
            self[rownumber][2] = tag.Part(tag_name='td')
            if col3[index]:  # this is the value
                self[rownumber][2][0] = tag.ClosedPart(tag_name="input", attribs={"name":name, "type":"radio"})
                if checked and (checked == col3[index]):
                    self[rownumber][2][0].attribs.update({"value":col3[index], "checked":"checked"})
                    # ensure only one item checked
                    checked = ''
                else:
                    self[rownumber][2][0].attribs.update({"value":col3[index]})

    @classmethod
    def description(cls):
        """Returns a text string to illustrate the widget"""
        return """
<table>  <!-- with widget id and class widget_class -->
  <tr> <!-- with header class -->
    <th> <!-- title1 --> </th>
    <th> <!-- title2 --> </th>
    <th> <!-- title3 --> </th>
  </tr>
  <tr> <!-- with class from row_classes -->
    <td> <!-- col1 text string --> </td>
    <td> <!-- col2 text string --> </td>
    <td><input type='radio' /> <!-- with name from 'radio_checked' widgfield and value from radiocol -->
    </td>
  </tr>
  <!-- rows repeated -->
</table>"""

