##############################################################################
#
# Copyright (c) 2007 Nexedi SARL and Contributors. All Rights Reserved.
#                    Romain Courteaud <romain@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
##############################################################################

from Products.Formulator import Widget, Validator
from Products.Formulator.Field import ZMIField
from Products.Formulator import StandardFields 
from Products.Formulator.DummyField import fields
from Products.PythonScripts.Utility import allow_class
from Products.ERP5Form import FormulatorPatch

from zLOG import LOG
from AccessControl import ClassSecurityInfo
from Products.Formulator.Errors import ValidationError

MINUTE_IN_SECOND = 60
HOUR_IN_SECOND = 3600
# DAY_IN_SECOND = 86400

class DurationWidget(FormulatorPatch.IntegerWidget):
  """
  Duration Widget is used to enter time duration.
  It may be used in movement of Labour (in Task, Calendat Period, ...).

  Time duration in ERP5 are saved ALWAYS IN SECOND.
  
  The field purpose is to display second quantity in hour, minute and second,
  in order to make it more readable.

  XXX This field is experimental, and unstable.
  Do not use it.
  """

  title = fields.StringField('title',
      title='Title. ' \
          '(Warning! Do not use this field!)',
                             description=(
      "The title of this field. This is the title of the field that "
      "will appear in the form when it is displayed. Required."),
                             default="",
                             required=1)

  def render_view(self, field, value, REQUEST=None, render_prefix=None):
    sub_field_render_list = []
    for title, sub_key, convertion in (('Hour', 'hour', HOUR_IN_SECOND),
                                ('Minute', 'minute', MINUTE_IN_SECOND)):
      if value == '':
        sub_value = ''
      else:
        sub_value, value = divmod(value, convertion)
      
      sub_field_render_list.append(self.render_sub_field_view(
                                     field, sub_value, REQUEST=REQUEST))
    # Render second
    sub_field_render_list.append(self.render_sub_field_view(
                                   field, value, REQUEST=REQUEST))
    return ':'.join(sub_field_render_list)

  def render(self, field, key, value, REQUEST, render_prefix=None):
    sub_field_render_list = []
    for title, sub_key, convertion in (('Hour', 'hour', HOUR_IN_SECOND),
                                ('Minute', 'minute', MINUTE_IN_SECOND)):
      if value == '':
        sub_value = ''
      else:
        sub_value, value = divmod(value, convertion)
      sub_field_render_list.append(self.render_sub_field(
                        field, key,
                        sub_value, REQUEST, sub_key))
    # Render second
    sub_field_render_list.append(self.render_sub_field(
                      field, key,
                      value, REQUEST, 'second'))
    return ':'.join(sub_field_render_list)

  def render_sub_field_view(self, field, value, REQUEST=None, render_prefix=None):
    """
    Render dynamically a subfield
    """
    return FormulatorPatch.IntegerFieldWidgetInstance.render_view(field, value,
                                                               REQUEST=REQUEST)

  def render_sub_field(self, field, key, value, REQUEST, keyword, render_prefix=None):
    """
    Render dynamically a subfield
    """
    return FormulatorPatch.IntegerFieldWidgetInstance.render(
              field,
              field.generate_subfield_key(keyword,
                                          key=key),
              value,
              REQUEST)

class DurationValidator(Validator.IntegerValidator):
  """
  Duration Validator
  """
  def validate(self, field, key, REQUEST):    
    second_value = None
    for sub_key, convertion in (('hour', HOUR_IN_SECOND),
                                ('minute', MINUTE_IN_SECOND),
                                ('second', 1)):
      second_value = self._validate_sub_field(
          field, key, REQUEST, sub_key, convertion, second_value,
      )
    return second_value
    
  def _validate_sub_field(self, field, key, REQUEST, sub_key, 
                          convertion, second_value):
    """
    Validates a subfield (as part of field validation).
    """
    sub_field_value = Validator.IntegerValidatorInstance.validate(
                              field,
                              field.generate_subfield_key(
                                sub_key, 
                                validation=1, key=key),
                              REQUEST
                              )
    if sub_field_value not in (None, ''):
      if second_value is not None:
        second_value += sub_field_value * convertion
      else:
        second_value = sub_field_value * convertion
    return second_value

DurationWidgetInstance = DurationWidget()
DurationFieldValidatorInstance = DurationValidator()

class DurationField(ZMIField):
  security = ClassSecurityInfo()
  meta_type = "DurationField"

  widget = DurationWidgetInstance
  validator = DurationFieldValidatorInstance
