import json
from urllib.parse import urlencode

from django.template import Context, Template

curl_template = """\
curl {% if method %}-X {{ method }}{% endif %}
{% if content_type %}-H 'content-type: {{ content_type }}'{% endif %}
{% if modifier %}{{ modifier }} {% endif %}{% if body %}'{{ body }}'{% endif %}
{{ url }}{% if query_params %}{{ query_params }}{% endif %}
{% if extra %}{{ extra }}{% endif %}
"""


def _curl_process_params(body, content_type, query_params):
    extra = None
    if query_params:
        try:
            query_params = urlencode(
                [(k, v.encode('utf8')) for k, v in query_params.items()]
            )
        except TypeError:
            pass
        query_params = '?' + str(query_params)
    if 'json' in content_type or 'javascript' in content_type:
        if isinstance(body, dict):
            body = json.dumps(body)
        modifier = '-d'
    # See http://curl.haxx.se/docs/manpage.html#-F
    # for multipart vs x-www-form-urlencoded
    # x-www-form-urlencoded is same way as browser,
    # multipart is RFC 2388 which allows file uploads.
    elif 'multipart' in content_type or 'x-www-form-urlencoded' in content_type:
        try:
            body = ' '.join([f'{k}={v}' for k, v in body.items()])
        except AttributeError:
            modifier = '-d'
        else:
            content_type = None
            modifier = '-F'
    elif body:
        body = str(body)
        modifier = '-d'
    else:
        modifier = None
        content_type = None
    # TODO: Clean up.
    return modifier, body, query_params, content_type, extra


def curl_cmd(url, method=None, query_params=None, body=None, content_type=None):
    if not content_type:
        content_type = 'text/plain'
    modifier, body, query_params, content_type, extra = _curl_process_params(
        body,
        content_type,
        query_params,
    )
    t = Template(curl_template)
    context = {
        'url': url,
        'method': method,
        'query_params': query_params,
        'body': body,
        'modifier': modifier,
        'content_type': content_type,
        'extra': extra,
    }
    return t.render(Context(context, autoescape=False)).replace('\n', ' ')
