# -*- coding: utf-8 -*-
'''
Created on Nov 14, 2014

from https://gist.github.com/gsakkis/601977
to correct https://code.djangoproject.com/ticket/10227

@author: ymh
'''
from django.core.exceptions import ObjectDoesNotExist
from django.db import models
from django.db.models import fields as django_fields

def isalambda(v):
    LAMBDA = lambda:0
    return isinstance(v, type(LAMBDA)) and v.__name__ == LAMBDA.__name__

class OneToOneField(models.OneToOneField):    
    def __init__(self, *args, **kwargs):
        self.related_default = kwargs.pop('related_default', None)
        #This is BAD. Did this to avoid more work in Django 1.7 migration
        #TODO: correct this
        if self.related_default == "lambda:":
            self.related_default = lambda instance: None
        super(OneToOneField, self).__init__(*args, **kwargs)

    def contribute_to_related_class(self, cls, related):
        setattr(cls, related.get_accessor_name(),
                SingleRelatedObjectDescriptor(related, self.related_default))

    def deconstruct(self):
        name, path, args, kwargs = super(OneToOneField, self).deconstruct()
        if self.related_default is not None:
            # this is VERY dirty and works only in our application.
            #TODO: correct this...
            if isalambda(self.related_default):
                kwargs['related_default'] = "lambda:"
            else:
                kwargs['related_default'] = self.related_default
        return name, path, args, kwargs

class SingleRelatedObjectDescriptor(django_fields.related.SingleRelatedObjectDescriptor):
    def __init__(self, related, default):
        super(SingleRelatedObjectDescriptor, self).__init__(related)
        self.default = default
        
    def __get__(self, instance, instance_type=None):
        try:
            return super(SingleRelatedObjectDescriptor, self).__get__(instance,
                                                                      instance_type)
        except ObjectDoesNotExist:
            if self.default is None:
                raise
            value = self.default(instance)
            setattr(instance, self.cache_name, value)
            if value is not None:
                setattr(value, self.related.field.get_cache_name(), instance)
            return value
        
