from __future__ import print_function, unicode_literals
import os, time, json
import click
from humanize import naturalsize
from .database import get_db

def abbrev(t):
    if t is None:
        return "-"
    if t > 1.0:
        return "%.3fs" % t
    if t > 1e-3:
        return "%.1fms" % (t*1e3)
    return "%.1fus" % (t*1e6)


def print_event(event):
    event_type, started, result, total_bytes, waiting_time, total_time = event
    followthrough = None
    if waiting_time and total_time:
        followthrough = total_time - waiting_time
    print("%17s: total=%7s wait=%7s ft=%7s size=%s (%s)" %
          ("%s-%s" % (event_type, result),
           abbrev(total_time),
           abbrev(waiting_time),
           abbrev(followthrough),
           naturalsize(total_bytes),
           time.ctime(started),
          ))

def show_usage(args):
    print("closed for renovation")
    return 0

def tail_usage(args):
    if not os.path.exists("relay.sqlite"):
        raise click.UsageError(
            "cannot find relay.sqlite, please run from the server directory"
        )
    db = get_db("relay.sqlite")
    # we don't seem to have unique row IDs, so this is an inaccurate and
    # inefficient hack
    seen = set()
    try:
        while True:
            old = time.time() - 2*60*60
            c = db.execute("SELECT * FROM `usage`"
                           " WHERE `started` > ?"
                           " ORDER BY `started` ASC", (old,))
            for row in c.fetchall():
                event = (row["type"], row["started"], row["result"],
                         row["total_bytes"], row["waiting_time"],
                         row["total_time"])
                if event not in seen:
                    print_event(event)
                    seen.add(event)
            time.sleep(2)
    except KeyboardInterrupt:
        return 0

def count_channels(args):
    if not os.path.exists("relay.sqlite"):
        raise click.UsageError(
            "cannot find relay.sqlite, please run from the server directory"
        )
    db = get_db("relay.sqlite")
    c_list = []
    c_dict = {}
    def add(key, value):
        c_list.append((key, value))
        c_dict[key] = value
    OLD = time.time() - 10*60
    def q(query, values=()):
        return list(db.execute(query, values).fetchone().values())[0]
    add("apps", q("SELECT COUNT(DISTINCT(`app_id`)) FROM `nameplates`"))

    add("total nameplates", q("SELECT COUNT() FROM `nameplates`"))
    add("waiting nameplates", q("SELECT COUNT() FROM `nameplates`"
                                " WHERE `second` is null"))
    add("connected nameplates", q("SELECT COUNT() FROM `nameplates`"
                                  " WHERE `second` is not null"))
    add("stale nameplates", q("SELECT COUNT() FROM `nameplates`"
                              " where `updated` < ?", (OLD,)))

    add("total mailboxes", q("SELECT COUNT() FROM `mailboxes`"))
    add("waiting mailboxes", q("SELECT COUNT() FROM `mailboxes`"
                                " WHERE `second` is null"))
    add("connected mailboxes", q("SELECT COUNT() FROM `mailboxes`"
                                 " WHERE `second` is not null"))

    stale_mailboxes = 0
    for mbox_row in db.execute("SELECT * FROM `mailboxes`").fetchall():
        newest = db.execute("SELECT `server_rx` FROM `messages`"
                            " WHERE `app_id`=? AND `mailbox_id`=?"
                            " ORDER BY `server_rx` DESC LIMIT 1",
                            (mbox_row["app_id"], mbox_row["id"])).fetchone()
        if newest and newest[0] < OLD:
            stale_mailboxes += 1
    add("stale mailboxes", stale_mailboxes)

    add("messages", q("SELECT COUNT() FROM `messages`"))

    if args.json:
        print(json.dumps(c_dict))
    else:
        for (key, value) in c_list:
            print(key, value)
    return 0

def count_events(args):
    if not os.path.exists("relay.sqlite"):
        raise click.UsageError(
            "cannot find relay.sqlite, please run from the server directory"
        )
    db = get_db("relay.sqlite")
    c_list = []
    c_dict = {}
    def add(key, value):
        c_list.append((key, value))
        c_dict[key] = value
    def q(query, values=()):
        return list(db.execute(query, values).fetchone().values())[0]

    add("apps", q("SELECT COUNT(DISTINCT(`app_id`)) FROM `nameplate_usage`"))

    add("total nameplates", q("SELECT COUNT() FROM `nameplate_usage`"))
    add("happy nameplates", q("SELECT COUNT() FROM `nameplate_usage`"
                              " WHERE `result`='happy'"))
    add("lonely nameplates", q("SELECT COUNT() FROM `nameplate_usage`"
                               " WHERE `result`='lonely'"))
    add("pruney nameplates", q("SELECT COUNT() FROM `nameplate_usage`"
                               " WHERE `result`='pruney'"))
    add("crowded nameplates", q("SELECT COUNT() FROM `nameplate_usage`"
                                " WHERE `result`='crowded'"))

    add("total mailboxes", q("SELECT COUNT() FROM `mailbox_usage`"))
    add("happy mailboxes", q("SELECT COUNT() FROM `mailbox_usage`"
                             " WHERE `result`='happy'"))
    add("scary mailboxes", q("SELECT COUNT() FROM `mailbox_usage`"
                             " WHERE `result`='scary'"))
    add("lonely mailboxes", q("SELECT COUNT() FROM `mailbox_usage`"
                              " WHERE `result`='lonely'"))
    add("errory mailboxes", q("SELECT COUNT() FROM `mailbox_usage`"
                              " WHERE `result`='errory'"))
    add("pruney mailboxes", q("SELECT COUNT() FROM `mailbox_usage`"
                              " WHERE `result`='pruney'"))
    add("crowded mailboxes", q("SELECT COUNT() FROM `mailbox_usage`"
                               " WHERE `result`='crowded'"))

    add("total transit", q("SELECT COUNT() FROM `transit_usage`"))
    add("happy transit", q("SELECT COUNT() FROM `transit_usage`"
                           " WHERE `result`='happy'"))
    add("lonely transit", q("SELECT COUNT() FROM `transit_usage`"
                            " WHERE `result`='lonely'"))
    add("errory transit", q("SELECT COUNT() FROM `transit_usage`"
                            " WHERE `result`='errory'"))

    add("transit bytes", q("SELECT SUM(`total_bytes`) FROM `transit_usage`"))

    if args.json:
        print(json.dumps(c_dict))
    else:
        for (key, value) in c_list:
            print(key, value)
    return 0
