import re
import time

from quixote import get_request, get_publisher, get_session
from quixote.directory import Directory

from wcs.qommon import _
from wcs.qommon.substitution import Substitutions
from wcs.qommon.form import Form, ValidatedStringWidget
from wcs.qommon import get_logger

from wcs.workflows import Workflow, WorkflowStatusJumpItem, register_item_class
from wcs.forms.common import FormStatusPage

from .abelium_domino_ui import (is_activated, abelium_domino_ws, get_client, get_family)
from . import abelium_domino_ws

class InternalCodeStringWidget(ValidatedStringWidget):
    regex = '\d*'

class AbeliumDominoRegisterFamilyWorkflowStatusItem(WorkflowStatusJumpItem):
    status = None
    description = N_('Abelium Domino: Register a Family')
    key = 'abelium-domino-register-family'
    category = 'interaction'
    label = None

    def render_as_line(self):
        return _('Register a Family into Abelium Domino')

    def get_family(self, formdata):
        try:
            user = formdata.get_user()
            if user:
                family = get_family(user)
                if family:
                    family.complete()
                return family
        except abelium_domino_ws.DominoException:
            pass
        return None

    def fill_form(self, form, formdata, user):
        family = self.get_family(formdata)
        if 'family_id' not in form._names:
            form.add(InternalCodeStringWidget, 'family_id',
                     title=_('Family internal code'),
                     value=family and family.code_interne.encode('utf8'),
                     hint=_('If a family internal code is present, the '
                            'family is updated, if not it is created'))
            form.add_submit('create_update_button%s' % self.id,
                    _('Create or update the family'))

    def update(self, form, formdata, user, evo):
        fid_widget = form.get_widget('family_id')
        code_interne = fid_widget.parse()
        try:
            code_interne = int(code_interne)
        except ValueError:
            raise ValueError('Le code interne est invalide')
        code_interne = '%05d' % code_interne
        family = get_client().get_family_by_code_interne(code_interne)
        if not family:
            raise ValueError('Le code interne est invalide')
        family.complete()
        self.extract_family(form, formdata, user, evo, family)
        family.save()
        return family

    def create(self, form, formdata, user, evo):
        family = abelium_domino_ws.Family(client=get_client())
        self.extract_family(form, formdata, user, evo, family)
        return family

    def extract_family(self, form, formdata, user, evo, family):
        formdef = formdata.formdef
        children = [abelium_domino_ws.Child() for i in range(5)]
        max_i = 0
        for field in formdef.fields:
            value = formdata.data.get(field.id)
            if value in (None, ''):
                continue
            if hasattr(field, 'date_in_the_past'):
                value = time.strftime('%Y%m%d', value)
            value = unicode(value, 'utf8')
            if field.prefill and \
               field.prefill.get('type') == 'formula':
                v = field.prefill.get('value', '').strip()
                i = None
                name = None
                m = re.search('domino_var_([^ ]*)_enfant([0-9]*)', v)
                m2 = re.search('domino_var_([^ ]*)', v)
                if m:
                    name, i = m.groups()
                    try:
                        i = int(i)
                    except ValueError:
                        continue
                    max_i = max(i, max_i)
                    print 'enfant', name, i-1, value
                    setattr(children[i-1], name, value)
                elif m2:
                    name = m2.group(1)
                    print 'family', name, value
                    setattr(family, name, value)
        for child1, child2 in zip(family.children, children[:max_i]):
            child1.__dict__.update(child2.__dict__)
        family.save()
        if max_i > len(family.children): # add new children
            for child in children[len(family.children):max_i]:
                family.add_child(child)

    def submit_form(self, form, formdata, user, evo):
        logger = get_logger()
        if form.get_submit() != 'create_update_button%s' % self.id:
            return
        try:
            if form.get_widget('family_id').parse():
                family = self.update(form, formdata, user, evo)
                msg = _('Sucessfully updated the family %s')
                log_msg = _('Sucessfully updated the family %(code)s of %(user)s')
            else:
                family = self.create(form, formdata, user, evo)
                msg = _('Sucessfully created the family %s')
                log_msg = _('Sucessfully created the family %(code)s of %(user)s')
            code_interne = family.code_interne.encode('utf8')
            msg = msg % code_interne
            logger.info(log_msg, {'code': code_interne, 'user': formdata.get_user()})
            form_user = formdata.get_user()
            form_user.abelium_domino_code_famille = code_interne
            form_user.store()
        except Exception, e:
            if form.get_widget('family_id').parse():
                msg = _('Unable to update family: %s') % str(e)
            else:
                msg = _('Unable to create family: %s') % str(e)
            evo.comment = msg
            logger.exception(msg  % formdata.get_user())
        else:
            evo.comment = msg
            wf_status = self.get_target_status()
            if wf_status:
                evo.status = 'wf-%s' % wf_status[0].id
        return False

    def is_available(self, workflow=None):
        return get_publisher().has_site_option('domino')
    is_available = classmethod(is_available)

register_item_class(AbeliumDominoRegisterFamilyWorkflowStatusItem)
