# -*- coding: utf-8 -*-
from decimal import Decimal

from django.conf import settings
from django.core.serializers.json import DateTimeAwareJSONEncoder
from django.db import models
from django.forms.models import ModelMultipleChoiceField
from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from django.utils import simplejson
from django.contrib.contenttypes.models import ContentType

from commons import (get_form_class, change_foreing_key, apply_filters,
                     special_procesing, transmeta_procesing)


def save_ajax(request):
    if request.POST:
        try:
            post = request.POST.copy()
            application_form = post.get('application_form')
            form = post.get('form', None)
            content_type_id = post.get('content_type_id')
            obj_id = post.get('id')
            field = post.get('field')
            value = simplejson.loads(post.get('value'))
            filters = simplejson.loads(post.get('filters','[]'))
            is_cmsutils = post.get('is_cmsutils', False)
            form_class = get_form_class(form, content_type_id)
            model_class = form_class._meta.model
            contenttype = ContentType.objects.get(id=content_type_id)
            assert contenttype.model_class() is model_class # check for hacker attack by changing POST
            obj = get_object_or_404(model_class,id=obj_id)
            user = request.user
            if not user.is_staff and not user.is_superuser and getattr(obj, 'can_edit_this_object', None) and not getattr(obj, 'can_edit_this_object')(user):
                json_dict = simplejson.dumps({'errors': True})
            else:
                new_data = change_foreing_key(obj)
                if isinstance(form_class.base_fields[field], ModelMultipleChoiceField):
                    new_data[field] = value.split(',')
                else:
                    new_data[field] = value

                form_obj = form_class(data=new_data, instance=obj)
                if form_obj.is_valid():
                    current_language = request.session.get('django_language',
                                                        settings.LANGUAGE_CODE)
                    obj = form_obj.save(current_language)
                    value = getattr(obj, field)
                    value = special_procesing(form_obj[field], value)
                    value = transmeta_procesing(form_obj[field], value, obj,
                                            current_language)
                    value = apply_filters(value, filters)
                    if not value and not getattr(obj, 'can_be_value_none', True):
                        value = obj.text_empty_value
                    json_dict = json_encode({'errors':False, 'value': value})
                else:
                    python_dict = dict(form_obj.errors)
                    python_dict['errors'] = True
                    json_dict = json_encode(dict(python_dict))
        except: # very scary!!!!
            json_dict = simplejson.dumps({'errors': True})

        return HttpResponse(json_dict,mimetype='application/json')

def json_encode(data, ensure_ascii=False):
    """
    The main issues with django's default json serializer is that properties that
    had been added to a object dynamically are being ignored (and it also has 
    problems with some models).
    """
    def _any(data):
        ret = None
        if isinstance(data, list):
            ret = _list(data)
        elif isinstance(data, dict):
            ret = _dict(data)
        elif isinstance(data, Decimal):
            # json.dumps() cant handle Decimal
            ret = str(data)
        elif isinstance(data, models.query.QuerySet):
            # Actually its the same as a list ...
            ret = _list(data)
        elif isinstance(data, models.Model):
            ret = _model(data)
        else:
            try:
                ret = data.__unicode__()
            except:
                ret = data
        return ret

    def _model(data):
        return data.__unicode__()

    def _list(data):
        ret = []
        for v in data:
            ret.append(_any(v))
        return ret

    def _dict(data):
        ret = {}
        for k,v in data.items():
            ret[k] = _any(v)
        return ret

    ret = _any(data)

    return simplejson.dumps(ret, cls=DateTimeAwareJSONEncoder, ensure_ascii=ensure_ascii)