#!/usr/bin/python3
# coding=utf-8
import sys
import json
import re


def iosdiagJoinData(raw):
    postprocess_result = {
        "code": 0,
        "err_msg": "",
        "result": {}
    }
    if raw.startswith('fail'):
        postprocess_result["code"] = 1
        postprocess_result["err_msg"] = f"Diagnosis failed:\n{raw}"
        print(json.dumps(postprocess_result, indent=4))
        return

    raw = raw.strip()
    disks = []
    stat = {}
    stat["disks"] = {"data": [{'key': 0, 'value': 'overview'}]}
    stat["iolatencyOverview_overview"] = {
        "data": [{'key': 'Check Result', "value": "normal"},
                 {'key': "IOs of over threshold", "value": 0}]}
    stat["summary"] = "diagnose results: Normal, No slow IO over threshold"
    for s in raw.split('\n'):
        try:
            obj = json.loads(s)
        except Exception:
            continue
        if "percent" in str(obj):
            disks = [s['diskname'] for s in obj['summary']
                     if s['diskname'] not in disks]
            stat["disks"]["data"] = \
                [{'key': disks.index(d), 'value': d} for d in disks]
            for s in obj['summary']:
                diskIdx = 'iolatencyDistribution_'+s['diskname']
                if diskIdx not in stat.keys():
                    stat[diskIdx] = {"data": []}
                maxPercent = sorted(s['delays'],
                                    key=lambda e: (
                                        float(e['percent'].strip('%'))),
                                    reverse=True)[0]['percent']
                for delay in s['delays']:
                    text = 'Max: '+str(round(delay['max'], 1)) +\
                        ' AVG: '+str(round(delay['avg'], 1)) +\
                        ' Min: '+str(round(delay['min'], 1))
                    node = {
                        "key": delay['component'], "title": delay['component'],
                        "value": delay['percent'], "text": text}
                    percent = float(delay['percent'].strip('%'))
                    if delay['component'] != 'disk' and percent > 10:
                        node['level'] = 'warning'
                    if delay['percent'] == maxPercent:
                        node['level'] = 'error'
                    stat[diskIdx]["data"].append(node)
        elif 'totaldelay' in str(obj) or 'abnormal' in str(obj):
            for s in obj['summary']:
                isSeqData = False
                diskIdx = 'singleIO_'+s['diskname']
                if 'totaldelay' in str(obj):
                    diskIdx = 'singleIOMetrics_'+s['diskname']
                    isSeqData = True

                if diskIdx not in stat.keys():
                    stat[diskIdx] = {"data": []}

                idx = -1
                dupRm = []
                slowIOs = s['slow ios']
                for delay in slowIOs:
                    idx += 1
                    if idx > 0 and delay["time"] == slowIOs[idx-1]["time"]:
                        if (isSeqData and delay["totaldelay"] <= slowIOs[idx-1]["totaldelay"]) \
                            or (not isSeqData and
                                float(re.split(':| ', delay['abnormal'])[-2]) <=
                                float(re.split(':| ', slowIOs[idx-1]['abnormal'])[-2])):
                            dupRm.append(delay)
                        else:
                            dupRm.append(slowIOs[idx-1])
                for d in dupRm:
                    if d in slowIOs:
                        slowIOs.remove(d)

                if not isSeqData:
                    slowIOs = \
                        sorted(slowIOs,
                               key=lambda e: float(
                                   re.split(':| ', e['abnormal'])[-2]),
                               reverse=True)[:10]
                    stat[diskIdx]["data"] = slowIOs

                else:
                    for delay in slowIOs:
                        entry = {
                            "time": delay['time'], "total": delay['totaldelay']}
                        for d in delay['delays']:
                            entry[d['component']] = d['delay']
                        stat[diskIdx]["data"].append(entry)
    for d in disks:
        if 'singleIOMetrics_'+d in stat.keys():
            count = len(stat['singleIOMetrics_'+d]["data"])
            stat["iolatencyOverview_"+d] = {
                "data": [{'key': 'Check Result', "value": "abnormal"},
                         {'key': "IOs of over threshold", "value": count}]}
        if 'iolatencyDistribution_'+d in stat.keys():
            if 'Abnormal' not in stat["summary"]:
                stat["summary"] = "diagnose results: Abnormal, "
            delays = sorted(stat['iolatencyDistribution_'+d]["data"],
                            key=lambda e: (float(e['value'].strip('%'))),
                            reverse=True)
            maxDelayComp = delays[0]['key']
            stat["summary"] += \
                ("The IO of disk %s is slow, caused by high %s latency;" % (
                    d, maxDelayComp))
    postprocess_result['result'] = stat
    s = json.dumps(postprocess_result, indent=4)
    print(s)


def extract_params():
    path, res, task_id = sys.argv[1], "", sys.argv[2]
    with open(path, 'r') as tmp:
        res = tmp.read()
    return res, task_id


if __name__ == "__main__":
    res, _ = extract_params()
    iosdiagJoinData(res)
