import aiozipkin.transport as azt
import logging

from .adapter import StatsD
from tracuni.misc.select_coroutine import get_coroutine_decorator
async_decorator = get_coroutine_decorator()


class TracerTransport(azt.Transport):
    # noinspection PyProtectedMember
    def __init__(
            self,
            logging_conf,
            statsd_conf,
            loop,
            use_tornado=False,
    ):
        tracer_url = logging_conf.url
        send_interval = logging_conf.send_interval
        super(TracerTransport, self).__init__(
            tracer_url,
            send_interval=send_interval,
            loop=loop
        )
        self.loop = loop
        self.__tracer = logging_conf.name
        self.use_tornado = use_tornado

        statsd_conf = StatsD.read_statsd_configuration(statsd_conf)

        self.stats = None
        if statsd_conf.enable:
            self.stats = StatsD(statsd_conf._asdict())
            self.stats.connect()
        self.statsd_is_configured = statsd_conf.enable and self.stats

    @async_decorator
    def _send(self):
        data = self._queue[:]

        try:
            if self.statsd_is_configured:
                yield self._send_to_statsd(data)
        except Exception as e:
            logging.exception(e)

        try:
            if self.__tracer == 'zipkin':
                if self.use_tornado:
                    yield super(TracerTransport, self)._send()
                else:
                    yield from super(TracerTransport, self)._send()
            else:
                self._queue = []
        except Exception as e:
            logging.exception(e)

    @async_decorator
    def _send_to_statsd(self, data):
        if self.stats:
            for rec in data:
                name = rec['name']

                api_kind = name.split('::')[0]
                span_side = rec['kind']
                json_method = rec['tags'].get('data.method')
                json_response_code = str(rec['tags'].get('data.code'))
                widget_id = rec['tags'].get('app.widget')
                app_method = rec['tags'].get('app.method', '').split(':')[-1]
                rq_hostname = rec['tags'].get('rq.url.hostname')
                rsp_status = int(rec['tags'].get('rsp.status') or 0)
                rq_time = int(round(rec["duration"] / 1000000))


                if api_kind == 'http':
                    if span_side == 'CLIENT':
                        self.stats.http_request(rsp_status, rq_hostname, rq_time)
                    elif span_side == 'SERVER':
                        self.stats.response(json_response_code, widget_id, json_method)
                        self.stats.send_timer(
                            f"handler_timers,name={app_method},widget_id={widget_id},method={json_method}",
                            int(round(rec["duration"] / 1000))
                        )

                if api_kind == 'db':
                    self.stats.send_timer(
                        f"db_query_function,func_name=\"{app_method}\"",
                        int(round(rec["duration"] / 1000))
                    )
