#!/usr/bin/env python3
# #!/bin/env PYTHONUNBUFFERED="yes" python
"""
Copy JSON stats fifo into prometheus for local monitoring

Usage:
    felix-stats2prometheus [options] <fifo>

Options:
    --port N                    Port to run webserver on [default: 8000]
    -v, --verbose               Verbose output

Arguments:
    <fifo>                      Statistics FIFO (JSON) to read from
"""
import functools
import ndjson
import os
import sys

print = functools.partial(print, flush=True)  # noqa: curl A001

# add the ../python path to find felix python libs
sys.path.append(os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'python'))

sys.path.append(os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'felix-tag/examples'))

from docopt import docopt  # noqa: E402

from prometheus_client import start_http_server, Gauge  # noqa: E402

# from felix.felix_fifo_util import FelixFifoUtil  # noqa: E402

from felixtag import FELIX_TAG  # noqa: E402


# timestamp = Gauge('timestamp', 'Timestamp for checking')
prometheus = {}


def metric_to_prometheus(app, key, value, hostname=None, device=None, dma=None, thread=None, fid=None):

    pkey = 'felix_{}_{}'.format(app, key)

    if verbose:
        print(app, pkey, value, hostname, device, dma, thread, fid)

    if pkey not in prometheus:
        labels = []
        if hostname:
            labels.append('hostname')
        if device:
            labels.append('device')
        if dma:
            labels.append('dma')
        if thread:
            labels.append('thread')
        if fid:
            labels.append('fid')
        prometheus[pkey] = Gauge(pkey, "", labels)

    value = float(value)
    if fid:
        prometheus[pkey].labels(hostname=hostname, device=device, dma=dma, thread=thread, fid=fid).set(value)
    elif thread:
        prometheus[pkey].labels(hostname=hostname, device=device, dma=dma, thread=thread).set(value)
    elif dma:
        prometheus[pkey].labels(hostname=hostname, device=device, dma=dma).set(value)
    elif device:
        prometheus[pkey].labels(hostname=hostname, device=device).set(value)
    elif hostname:
        prometheus[pkey].labels(hostname=hostname).set(value)
    else:
        prometheus[pkey].set(value)


def to_prometheus(msg):
    # ts = time.mktime(datetime.datetime.strptime(msg['ts'], "%Y-%m-%dT%H:%M:%SZ").timetuple())
    # timestamp.set(ts)

    for hostname, value in msg['host'].items():
        for app, value in value['app'].items():  # noqa: B020
            for key, value in value.items():  # noqa: B020
                if key != 'device':
                    metric_to_prometheus(app, key, value, hostname)
                    continue
                for device, value in value.items():  # noqa: B020
                    for key, value in value.items():  # noqa: B020
                        if key != 'dma':
                            metric_to_prometheus(app, key, value, hostname, device)
                            continue
                        for dma, value in value.items():  # noqa: B020
                            for key, value in value.items():  # noqa: B020
                                if key != 'thread':
                                    metric_to_prometheus(app, key, value, hostname, device, dma)
                                    continue
                                for thread, value in value.items():  # noqa: B020
                                    for key, value in value.items():  # noqa: B020
                                        if key != 'fid':
                                            metric_to_prometheus(app, key, value, hostname, device, dma, thread)
                                            continue
                                        for fid, value in value.items():  # noqa: B020
                                            for key, value in value.items():  # noqa: B020
                                                metric_to_prometheus(app, key, value, hostname, device, dma, thread, fid)


def read_fifo(fifo):
    while True:
        if verbose:
            print("Opened fifo", fifo)

        with open(fifo, 'r') as pipe:
            reader = ndjson.reader(pipe)
            for msg in reader:
                # print(msg)
                to_prometheus(msg)

        if verbose:
            print("Fifo closed")


if __name__ == "__main__":
    """fifo2elink."""
    args = docopt(__doc__, version=sys.argv[0] + " " + FELIX_TAG)

    verbose = args['--verbose']

    fifo = args['<fifo>']

    start_http_server(int(args['--port'], 0))

    if verbose:
        print("Read...")
    read_fifo(fifo)
