import urllib2

from urllib import quote

try:
    import simplejson as json
except ImportError:
    try:
        import json
    except ImportError:
        try:
            from django.utils import simplejson as json
        except ImportError:
            raise ImportError('A json library is required to use this python library. Lol, yay for being verbose. ;)')

from .exceptions import *


class MailSnake(object):
    def __init__(self, apikey='', extra_params=None, api='api'):
        """
            Cache API key and address.
        """
        self.apikey = apikey
        self.api = api

        self.default_params = {'apikey': apikey}
        extra_params = extra_params or {}
        self.default_params.update(extra_params)

        if '-' in self.apikey:
            self.dc = self.apikey.split('-')[1]
        api_info = {
            'api':('api','1.3/?method='),
            'sts':('sts','1.0/'),
            'export':('api','export/1.0/')
        }
        self.api_url = 'https://%s.%s.mailchimp.com/%s' % \
                       ((dc,) + api_info[api])

    def call(self, method, params=None):
        url = self.api_url + method
        params = params or {}
        params.update(self.default_params)

        if self.api == 'api':
            post_data = urllib2.quote(json.dumps(all_params))
            headers = {'Content-Type':'application/json'}
        else:
            headers = {'Content-Type':'application/x-www-form-urlencoded'}
            post_data = http_build_query(all_params)
            if self.api == 'sts':
                url += '.json/'
            else:
                # Use GET for the Export API
                url += '?' + post_data
                post_data = ''
        request = urllib2.Request(url, post_data, headers)

        try:
            response = urllib2.urlopen(request)
        except urllib2.URLError, e:
            raise NetworkTimeoutException(str(e.reason))
        except urllib2.HTTPError, e:
            raise HTTPRequestException(e.code)

        try:
            rsp = json.loads(response.read())
        except json.JSONDecodeError, e:
            raise ParseException(e.reason)

        if not isinstance(rsp, (int, bool, basestring)) and 'error' in rsp and 'code' in rsp:
            try:
                Err = exception_for_code(rsp['code'])
            except KeyError:
                raise SystemException(rsp['error'])
            raise Err(rsp['error'])

        return rsp

    def __getattr__(self, method_name):

        def get(self, *args, **kwargs):
            params = dict((i, j) for (i, j) in enumerate(args))
            params.update(kwargs)
            return self.call(method_name, params)

        return get.__get__(self)

##################################################
# http://www.codigomanso.com/en/2010/04/http_build_query-para-python/
# By Pau Sanchez
# Mimics the behaviour of http_build_query PHP function
# This method can be useful for sending data to flash applications
##################################################
def http_build_query(params, topkey = ''): 
    if len(params) == 0:
        return ""

    result = ""
 
    # is a dictionary?
    if type (params) is dict:
        for key in params.keys():
            newkey = quote (key)
            if topkey != '':
              newkey = topkey + quote('[' + key + ']')
 
            if type(params[key]) is dict:
                result += http_build_query (params[key], newkey)

            elif type(params[key]) is list:
                i = 0
                for val in params[key]:
                    result += newkey + quote('[' + str(i) + ']') + \
                              "=" + quote(str(val)) + "&"
                    i = i + 1

            # boolean should have special treatment as well
            elif type(params[key]) is bool:
                result += newkey + "=" + quote(str(int(params[key]))) + "&"

            # assume string (integers and floats work well)
            else:
                result += newkey + "=" + quote(str(params[key])) + "&"

    # remove the last '&'
    if (result) and (topkey == '') and (result[-1] == '&'):
        result = result[:-1]

    return result

@@ -309,42 +309,114 @@
 use 
-this python library. Lol, yay for 
+' + %5C%0A                             'this python library. Lol, yay for ' + %5C%0A                             '
 bein
@@ -1121,16 +1121,21 @@
       ((
+self.
 dc,) + a
@@ -1379,20 +1379,16 @@
 n.dumps(
-all_
 params))
@@ -1490,32 +1490,55 @@
 %7B'Content-Type':
+%0A                      
 'application/x-w
@@ -1603,12 +1603,8 @@
 ery(
-all_
 para
@@ -2110,32 +2110,159 @@
 )%0A%0A        try:%0A
+            if self.api == 'export':%0A                rsp = %5Bjson.loads(i) for i in response.readlines()%5D%0A            else:%0A    
             rsp 
@@ -2366,22 +2366,23 @@
 ption(e.
-reason
+message
 )%0A%0A     
@@ -2436,16 +2436,34 @@
 g)) and 
+%5C%0A                
 'error' 
@@ -3357,18 +3357,18 @@
  return 
-%22%22
+''
 %0A%0A    re
@@ -3374,18 +3374,18 @@
 esult = 
-%22%22
+''
 %0A %0A    #
@@ -3492,17 +3492,16 @@
  = quote
- 
 (key)%0A  
@@ -3527,16 +3527,18 @@
  != '':%0A
+  
         
@@ -3670,17 +3670,16 @@
 ld_query
- 
 (params%5B
@@ -3692,17 +3692,16 @@
 newkey)%0A
-%0A
         
@@ -3897,19 +3897,19 @@
         
-%22=%22
+'='
  + quote
@@ -3921,19 +3921,19 @@
 val)) + 
-%22&%22
+'&'
 %0A       
@@ -3955,17 +3955,16 @@
 = i + 1%0A
-%0A
         
@@ -4086,37 +4086,65 @@
 ult += newkey + 
-%22=%22 +
+'=' + %5C%0A                         
  quote(str(int(p
@@ -4155,28 +4155,27 @@
 s%5Bkey%5D))) + 
-%22&%22%0A
+'&'
 %0A           
@@ -4271,20 +4271,25 @@
  += 
+str(
 newkey
+)
  + 
-%22=%22
+'='
  + q
@@ -4317,11 +4317,11 @@
 ) + 
-%22&%22
+'&'
 %0A%0A  

fix export api and small pep8 fixes