#!/usr/bin/env python3
"""
 CIJOE Metric Plotter
"""
import argparse
import sys
import os
import yaml
import cij.analyser
import cij.util
import cij


def collect_metrics(args):
    """Collect all metrics found in 'metrics.yml' of testcase _aux folders"""

    metrics = []
    for root, _, _ in os.walk(args.output):
        yml_fpath = os.path.join(root, "_aux", "metrics.yml")
        if not (root.endswith(".sh") and os.path.exists(yml_fpath)):
            continue

        with open(yml_fpath, 'r', encoding="UTF-8") as yml_file:
            metrics.extend(yaml.safe_load(yml_file))

    return metrics


def parse_args():
    """Parse command-line arguments for CIJOE Metric Dumper"""

    # Parse the Command-Line
    prsr = argparse.ArgumentParser(
        description='cij_plotter - CIJOE Metric Dumper',
        formatter_class=argparse.ArgumentDefaultsHelpFormatter
    )

    prsr.add_argument(
        '--output',
        help="Path to test output",
        default=os.getcwd()
    )

    prsr.add_argument(
        '--metric',
        help="The thing of interest",
        choices=["iops", "lat", "bwps"],
        default="lat"
    )
    prsr.add_argument(
        '--bs',
        help="Only dump samples matching this block-size"
    )
    prsr.add_argument(
        '--iodepth',
        help="Only dump samples matching this iodepth"
    )

    args = prsr.parse_args()

    args.output = cij.util.expand_path(args.output)
    if not os.path.exists(args.output):
        cij.err(f"plotter:output: {args.output}, does not exist")
        return None

    return args


def metric_to_str(metric, val):
    """Convert the given metric to string"""

    if metric == "lat":
        return "%d" % (float(val) * 1000000000.0)

    return str(val)


def sec_to_nsec(val):
    """Convert seconds to nano-seconds"""

    return int(val * 1000000000.0)


def main():
    """
    Entry point for Plotter, parse arguments, normalize metrics and plot
    """

    args = parse_args()
    if args is None:
        cij.err("plotter: failed parsing command-line args")
        return 1

    dset = {}

    def suite_select(item):
        """Selects ["ctx"]["tsuite_name"] as sort-key"""

        return item["ctx"]["tsuite_name"]

    for metric in sorted(collect_metrics(args), key=suite_select):

        if args.bs and args.bs != metric["ctx"]["bs"]:
            continue
        if args.iodepth and args.iodepth != metric["ctx"]["iodepth"]:
            continue

        ident = metric["ctx"]["tsuite_name"]

        if ident not in dset:
            dset[ident] = {
                "bs": metric["ctx"]["bs"],
                "iodepth": metric["ctx"]["iodepth"],
                "lat": [],
                "stddev": [],
                "var": []
            }

        dset[ident]["lat"].append(sec_to_nsec(metric[args.metric]))
        dset[ident]["stddev"].append(int(metric["stddev"]))
        dset[ident]["dist"] = max(dset[ident]["lat"]) - min(dset[ident]["lat"])

    for ident in dset.items():
        sample = dset[ident]
        print("%s: { lat: [%s], stddev: [%s], dist: [%s], min: %d}" % (
            ident,
            ", ".join([str(x) for x in sample["lat"]]),
            ", ".join(["%.f" % x for x in sample["stddev"]]),
            sample["dist"],
            min(sample["lat"])
        ))

    return 0


if __name__ == "__main__":
    sys.exit(main())
