import json

from django.views.decorators.http import require_http_methods

from staff.lib.decorators import (
    responding_json,
    use_request_lang,
    available_for_external,
)
from staff.lib.forms.staff_form_grid import StaffFormGrid
from staff.lib.utils.qs_values import (
    localize,
    extract_related,
)

from ..controllers import department as ctl
from ..forms.department import DepartmentForm
from staff.lib.forms.errors import (
    invalid_json_error,
    form_data_error,
    default_error,
)
from ..permissions.utils import observer_has_perm

import logging
logger = logging.getLogger('person_profile.edit_views.edit_department_view')

FORM_NAME = 'department'


@responding_json
@available_for_external
@require_http_methods(['GET', 'POST'])
@observer_has_perm('edit_department')
@use_request_lang
def edit_department(request, login):
    if request.method == 'GET':
        # TODO login validation and error
        data = {
            'department_%s' % k: v for k, v
            in localize(extract_related(
                ctl.get_initial(login), 'department')
            ).items()
        }
        # да, костылик, надо будет думать, как его красивее делать, а потом
        # чинить staff_form.field_StaffSuggestField_as_front_dict
        data['department_id_caption'] = data['department_name']
        return {
            FORM_NAME: StaffFormGrid(DepartmentForm, initial=[data]).as_front_dict()
        }

    try:
        form_data = json.loads(request.body)[FORM_NAME][0]
    except ValueError:
        logger.exception('Wrong JSON: %s', request.body)
        return invalid_json_error(request.body), 400
    except (KeyError, IndexError):
        logger.exception('Cannot find form data: %s', FORM_NAME)
        return form_data_error(FORM_NAME), 400

    grid = StaffFormGrid(DepartmentForm, data=[form_data])

    if not grid.is_valid():
        return {'errors': {FORM_NAME: grid.errors()}}
    try:
        ctl.update(login, grid.cleaned_data[0], request.user)
    except ctl.DepartmentError:
        return default_error(), 500

    return {'target': {}}
