from django.db import models
import datetime
from django.utils.translation import ugettext_lazy as _

class Duration(datetime.timedelta):
    def __str__(self):
        hours   = self.days * 24
        minutes = self.seconds / 60
        seconds = self.seconds % 60
    
        return "%.2d:%.2d:%.2d" % (hours, minutes, seconds)

    @staticmethod
    def fromstr(str):
        test = re.match('^([0-9]+)(?::([0-9]+)(?::([0-9]+))?)?$', str)
        if test:
            groups = test.groups()
            return Duration(hours=int(groups[0]), minutes=int(groups[1]), seconds=int(groups[2]))
        else:
            raise ValueError("Malformed duration string: " + str)

    def as_seconds(self):
        return self.days * 24 * 3600 + self.seconds
            
# The following is based on Django TimeField
class DurationField(models.Field):
    description = _("Duration")

    __metaclass__ = models.SubfieldBase

    default_error_messages = {
        'invalid': _('Enter a valid duration in HH:MM[:ss[.uuuuuu]] format.'),
    }

    def get_internal_type(self):
        return 'TimeField'

    def to_python(self, value):
        if value is None:
            return None
        if isinstance(value, datetime.time):
            return Duration(hours=value.hour, minutes=value.minute, seconds=value.second)
        if isinstance(value, datetime.datetime):
            # Not usually a good idea to pass in a datetime here (it loses
            # information), but this can be a side-effect of interacting with a
            # database backend (e.g. Oracle), so we'll be accommodating.
            return self.to_python(value.time())

        try:
            value = Duration.fromstr(value)
        except ValueError:
            raise exceptions.ValidationError(self.error_messages['invalid'])
            
    def get_prep_value(self, value):
        return self.to_python(value)

    def get_db_prep_value(self, value, connection, prepared=False):
        # Casts times into the format expected by the backend
        return unicode(value)

    def value_to_string(self, obj):
        val = self._get_val_from_obj(obj)
        if val is None:
            data = ''
        else:
            data = unicode(val)
        return data

    def formfield(self, **kwargs):
        defaults = {'form_class': forms.TimeField}
        defaults.update(kwargs)
        return super(DurationField, self).formfield(**defaults)
            
