"""
A two-part middleware which modifies request.COOKIES and adds a set and delete method.

    `set` matches django.http.HttpResponse.set_cookie
    `delete` matches django.http.HttpResponse.delete_cookie

MIDDLEWARE_CLASSES = (
    'django_cookies.CookiePreHandlerMiddleware',
    ...
    'django_cookies.CookiePostHandlerMiddleware',
)

def my_view(request):
    request.COOKIES.set([args])
    ...
    return response
"""

from Cookie import SimpleCookie, Morsel
from django.utils.encoding import smart_unicode, smart_str
import copy

class CookiePreHandlerMiddleware(object):
    """
    This middleware modifies request.COOKIES and adds a set and delete method.

    `set` matches django.http.HttpResponse.set_cookie
    `delete` matches django.http.HttpResponse.delete_cookie

    This should be the first middleware you load.
    """
    def process_request(self, request):
        cookies = CookieHandler()
        for k, v in request.COOKIES.iteritems():
            cookies[k] = str(v)
        request.COOKIES = cookies
        request._orig_cookies = copy.deepcopy(request.COOKIES)

class CookiePostHandlerMiddleware(object):
    """
    This middleware modifies updates the response will all modified cookies.

    This should be the last middleware you load.
    """
    def process_response(self, request, response):
        if hasattr(request, '_orig_cookies') and request.COOKIES != request._orig_cookies:
            for k,v in request.COOKIES.iteritems():
                if request._orig_cookies.get(k) != v:
                    dict.__setitem__(response.cookies, k, v)
        return response

class StringMorsel(Morsel):
    def __str__(self):
        return smart_str(self.value)

    def __eq__(self, a):
        if isinstance(a, str):
            return smart_str(self) == a
        elif isinstance(a, Morsel):
            return a.output() == self.output()
        return False

    def __ne__(self, a):
        if isinstance(a, str):
            return smart_str(self) != a
        elif isinstance(a, Morsel):
            return a.output() != self.output()
        return True

    def __repr__(self):
        return smart_unicode(self)

    def decode(self, *args):
        return self.__repr__()

class CookieHandler(SimpleCookie):
    def __set(self, key, real_value, coded_value):
        """Private method for setting a cookie's value"""
        M = self.get(key, StringMorsel())
        M.set(key, real_value, coded_value)
        dict.__setitem__(self, key, M)

    def __setitem__(self, key, value):
        """Dictionary style assignment."""
        rval, cval = self.value_encode(value)
        self.__set(key, rval, cval)

    def set(self, key, value='', max_age=None, expires=None, path='/', domain=None, secure=None):
        self[key] = value
        for var in ('max_age', 'path', 'domain', 'secure', 'expires'):
            val = locals()[var]
            if val is not None:
                self[key][var.replace('_', '-')] = val

    def delete(self, key, path='/', domain=None):
        self[key] = ''
        if path is not None:
            self[key]['path'] = path
        if domain is not None:
            self[key]['domain'] = domain
        self[key]['expires'] = 0
        self[key]['max-age'] = 0
