import argparse
import re
import sys
import glob, os
from collections import defaultdict

from data.chum import chumpy
from vehicle.sensors.cameras.diagnostics.diagnostic_pb2  import CameraMetric
from diagnostic_msgs.msg import DiagnosticArray

from base.hwsd_client.v2 import RunBuilderFactory, RunBuilderBaseException

def read_file_value(params, path, filename):
    with open(path+'/'+filename, 'r') as file:
        data = file.read().replace('\n', '')
    params[filename].append(data)
    return data

def escape_ansi(line):
    ansi_escape = re.compile(r'(?:\x1B[@-_]|[\x80-\x9F])[0-?]*[ -/]*[@-~]')
    return ansi_escape.sub('', line)

def read_link_margins(params, path):
    with open(path+'/link_margin_stdout', 'r') as lm_file:
        label=''
        for line in lm_file:
            if "Forward" in line or "Reverse" in line:
                #TODO output this in a more structured format
                params[label].append(escape_ansi(line.strip()))
            else:
                label = escape_ansi(line)

def upload_to_hwsd(params, path, passing, serial, level):
    run_builder = RunBuilderFactory.get_builder(
        "framegrabber_iqc",
        "1.0.1",
        RunBuilderFactory.TestTypes.COMPONENT_LEVEL,
        serial,
        "board_level",
        level,
    )

    for field, value in params.items():
        print field, value
        run_builder.add_param(field, value)

    try:
        run_builder.file_upload(path)
    except (RunBuilderBaseException, Exception) as error:
        print "Error uploading artifacts:", error

    run_builder.commit(passing)


def local_parse(path, upload, stage):

    chum_store = chumpy.Store.createEmpty()
    chum_store.addInput(path)

    data = chumpy.uri.rangesPerVehicleFromLocalStore(chum_store)
    print data
    range_time = 0
    for vehicle, chum_range in data[''].items():
        chum_reader = chumpy.Reader.create(chum_store, chum_range)
        range_time += chum_range.end_time - chum_range.start_time
    range_time /= 10**9
    if range_time < 20:
        print "Error: not enough test time, check that cammux and logger ran:", range_time
        sys.exit(1)
    if range_time > 1000:
        print "Error: please clear your logs too much time elapsed:", range_time
        sys.exit(1)

    # I want to take the ROS diagnostics messages (ick!) and produce an array
    # of statuses for each name appears in the status messages
    diagnostic_items = []

    # Collect diagnostic group names.
    diagnostic_names = set()
    params = defaultdict(list)
    packet_errors = {}
    frame_drops = {}

    start = 0
    end = 0
    for msg in chum_reader:
        frame = {}
        if msg.ros_md5 != DiagnosticArray._md5sum:
            continue

        diagnostic_msg = DiagnosticArray()
        diagnostic_msg.deserialize(msg.getData())
        end = diagnostic_msg.header.stamp.to_sec()

        if start == 0:
            start = end
        if end - start < 20:
            continue

        #print diagnostic_msg
        for item in diagnostic_msg.status:
            if "Cameras" in item.name and "cammux" not in item.name and "artifact" not in item.name:
                if "Fault" in item.message:
                    print "FAULT: "
                    print item.name
                    diagnostic_names.add(item.message)
                for v in item.values:
                    if v.value not in params[v.key]:
                        params[v.key].append(v.value)

                if item.name not in packet_errors:
                    packet_errors[item.name] = 0
                if item.name not in frame_drops:
                    frame_drops[item.name] = 0
                for v in item.values:
                    if "frames_dropped" in v.key:
                        try:
                            if int(v.value) != 0:
                               frame_drops[item.name] = frame_drops[item.name] + int(v.value)
                        except:
                            pass
                    if "packet_errors" in v.key:
                        try:
                            if int(v.value) != 0:
                                packet_errors[item.name] = packet_errors[item.name] + int(v.value)
                        except:
                            pass

    params["packet_errors_total"] = packet_errors
    params["frame_drops_total"] = frame_drops
    duration = end - start - 20
    if duration < 10:
        print "Error: not enough data collected!"
        sys.exit(1)
    print "Analyzed %d seconds" % duration

    read_link_margins(params, path)

    serial = read_file_value(params, path, "framegrabber_serial")
    part = read_file_value(params, path, "framegrabber_part")
    operator_id = read_file_value(params, path, "operator_id")
    harness_id = read_file_value(params, path, "harness_id")

    for field, value in params.items():
        print field, value

    if upload == 'true':
        upload_to_hwsd(params, path, len(diagnostic_names)==0, serial, stage)

    if len(diagnostic_names) > 0:
        print diagnostic_names
        print "Error, diagnotic faults ^"
        sys.exit(1)
    else:
        print "Success"
        sys.exit(0)

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--path", required=True, help="Path to the chum data")
    parser.add_argument("--upload", required=True, help="Upload to HWSD")
    parser.add_argument("--stage", required=True, help="test_stage")
    args = parser.parse_args()
    local_parse(args.path, args.upload, args.stage)
