from datetime import datetime
from itertools import chain
import operator

from django.conf import settings
from django.http import Http404

from staff.lib.decorators import available_by_center_token

from staff.person.models import Staff

from staff.gap.models import Gap, Workflow
from staff.gap.controllers.staff_utils import GapsByPersons

from . import ApiView


_def_gap_fields = (
    'staff__login_ld',
    'staff__login',
    'staff__id',
    'gap_type__name',
    'gap_type__id',
    'left_edge',
    'right_edge',
    'description'
)
_full_gap_fields = ApiView.full_fields(Gap, {
    'gap_type': Workflow,
    'staff': Staff
})


@available_by_center_token
class AbsenceByUserView(ApiView):

    entities = ('absence', 'user')

    def prepare_data(self, users, *args, **kwargs):
        if hasattr(self.request.user, 'get_profile'):
            observer_tz = self.request.user.get_profile().tz
        else:
            observer_tz = settings.TIME_ZONE

        person_list = users.split('|')
        if not len(person_list):
            raise Http404()

        wfs = {wf['name']: wf for wf in Workflow.objects.values()}

        fields = self.get_fields(
            Gap, 'fields', _def_gap_fields, _full_gap_fields
        )
        field_getters = {
            f: self.get_field_getter(f, wfs)
            for f in fields
            if self.get_field_getter(f, wfs) is not None
        }

        gaps = GapsByPersons(datetime.now(), observer_tz=observer_tz)

        if person_list[0].isdigit():
            try:
                person_list = [int(p) for p in person_list]
            except ValueError:
                raise Http404('Incorect login.')
            gaps = gaps.get_by_ids(person_list)
        else:
            gaps = gaps.get_by_logins(person_list)

        gaps = [
            {f: getter(gap) for f, getter in field_getters.items()}
            for gap in chain.from_iterable(gaps.values())
        ]

        self.data = gaps

    fields_map = {
        'staff__login_ld': operator.itemgetter('person_login'),
        'staff__login': operator.itemgetter('person_login'),
        'staff__id': operator.itemgetter('person_id'),
        'left_edge': lambda g: datetime.combine(g['left_edge'], datetime.min.time()),
        'right_edge': lambda g: datetime.combine(g['right_edge'], datetime.min.time()),
        'description': operator.itemgetter('comment'),
    }

    def get_field_getter(self, field, wfs):
        if field.startswith('gap_type__'):
            return lambda g: wfs[g['workflow']][field.split('__', 1)[1]]
        return self.fields_map.get(field)
