# coding=utf-8
from __future__ import unicode_literals, absolute_import

import json
import logging

from django.conf import settings
from elasticsearch.client.utils import _make_path
from elasticsearch.client.utils import query_params
from elasticsearch.connection.base import logger, tracer


def _format_description(description):
    place_holder_len = len(description) + 10
    format_description = "{header}\n{description}\n{footer}".format(
        header="*" * place_holder_len,
        description="***  " + description + "  ***",
        footer="*" * place_holder_len
    )

    print (format_description)


def _pprint_es_request_body(body):
    _format_description("Your current ES request body is as following")
    print (json.dumps(body, indent=2))
    print ('\n' * 3)


@query_params('_source', '_source_exclude', '_source_include',
              'allow_no_indices', 'analyze_wildcard', 'analyzer', 'default_operator',
              'df', 'expand_wildcards', 'explain', 'fielddata_fields', 'fields',
              'from_', 'ignore_unavailable', 'lenient', 'lowercase_expanded_terms',
              'preference', 'q', 'request_cache', 'routing', 'scroll', 'search_type',
              'size', 'sort', 'stats', 'suggest_field', 'suggest_mode',
              'suggest_size', 'suggest_text', 'terminate_after', 'timeout',
              'track_scores', 'version')
def new_search(self, index=None, doc_type=None, body=None, params=None):
    _pprint_es_request_body(body)
    if 'from_' in params:
        params['from'] = params.pop('from_')

    if doc_type and not index:
        index = '_all'

    _, data = self.transport.perform_request('GET', _make_path(index,
                                                               doc_type, '_search'), params=params, body=body)
    return data


es_host = settings.ES_V2_HOSTS[0]['host']


def new_log_request_success(self, method, full_url, path, body, status_code, response, duration):
    """ Log a successful API call.  """

    #  TODO: optionally pass in params instead of full_url and do urlencode only when needed
    def _pretty_json(data):
        # pretty JSON in tracer curl logs
        try:
            return json.dumps(json.loads(data), sort_keys=True, indent=2, separators=(',', ': ')).replace("'",
                                                                                                          r'\u0027')
        except (ValueError, TypeError):
            # non-json data or a bulk request
            return data

    # body has already been serialized to utf-8, deserialize it for logging
    # TODO: find a better way to avoid (de)encoding the body back and forth
    if body:
        body = body.decode('utf-8')

    logger.info(
        '%s %s [status:%s request:%.3fs]', method, full_url,
        status_code, duration
    )
    logger.debug('> %s', body)
    logger.debug('< %s', response)

    if tracer.isEnabledFor(logging.INFO):
        # include pretty in trace curls
        path = path.replace('?', '?pretty&', 1) if '?' in path else path + '?pretty'
        if self.url_prefix:
            path = path.replace(self.url_prefix, '', 1)
        tracer.info("curl -X%s 'http://%s:9200%s' -d '%s'", method, es_host, path, _pretty_json(body) if body else '')

    if tracer.isEnabledFor(logging.DEBUG):
        tracer.debug('#[%s] (%.3fs)\n#%s', status_code, duration,
                     _pretty_json(response).replace('\n', '\n#') if response else '')


from elasticsearch.connection.base import Connection


def patch_es_log():
    logger.setLevel(logging.DEBUG)
    handler = logging.StreamHandler()
    logger.addHandler(handler)
    setattr(Connection, 'log_request_success', new_log_request_success)


def patch_all(es_log=True):
    if es_log is True:
        patch_es_log()
