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


import json
import six
from ...core.data import DataSink
from ...core.es_data import EsDataSink
from ..queue import get_redis_connection
from ... import settings as ds_settings


def _rec_convert_for_debug(message):
    if isinstance(message, dict):
        return {
            k: _rec_convert_for_debug(v)
            for k, v in message.items()
        }
    if isinstance(message, list):
        return [
            _rec_convert_for_debug(v)
            for v in message
        ]
    if message is None or isinstance(message, (int, long, float, str, unicode)):
        return message
    try:
        return repr(message)
    except:
        try:
            return "<TYPE:{}>".format(repr(type(message)))
        except:
            return "<UNKNOWN>"


class TracedDataSink(DataSink):

    def __init__(self, name, sink):
        assert isinstance(name, six.string_types)
        assert isinstance(sink, DataSink)
        self._name = name
        self._sink = sink

    @staticmethod
    def __publish(message):
        message_json = json.dumps(_rec_convert_for_debug(message))
        get_redis_connection().publish(ds_settings.REDIS_ES_WRITE_CHANNEL_NAME, message_json)

    def __setitem__(self, key, value):
        self.__publish({
            'name': self._name,
            'action': 'set',
            'key': key,
            'value': value,
        })
        self._sink[key] = value

    def __delitem__(self, key):
        self.__publish({
            'name': self._name,
            'action': 'del',
            'key': key,
        })
        del self._sink[key]


class TracedESDataSink(TracedDataSink):

    def __init__(self, es_type):
        super(TracedESDataSink, self).__init__(
            name=es_type,
            sink=EsDataSink(es_type=es_type),
        )

