#!/usr/bin/env python

#######################################################
# Copyright Trimble Inc 2021
# Purpose: For plotting out data from Record 33 type 4 (RTX / MSS / Omnistar Signal Info) from multiple T0x files 
#          Usually used for reset / reboot tests that results in multiple T0x files
#          
# Plots:
# - All times to first valid 33:4 record from first position timestamp
#
# Contributor(s): Joshua_McLean@Trimble.com, 
#######################################################

import argparse
from ast import arg
from cmath import nan
from operator import countOf
import os
from re import A
import sys

import glob
import matplotlib
import mutils as m
import numpy as np

from matplotlib.ticker import (MultipleLocator, FormatStrFormatter,
                               AutoMinorLocator)

parser = argparse.ArgumentParser(description='Generate useful .png plots for record 35:4 for multiple T0x files')
parser.add_argument('pattern', help='T0x file search pattern, i.e. "*.T04"')
parser.add_argument('--label', help='Label to include in plot(s)', default=None, type=str)
parser.add_argument('--csv', help='Output a CSV file listing T04 file name and times', action='store_true')
parser.add_argument('--fig', help='Output plots in Matlab fig instead of PNG', action='store_true')
args = parser.parse_args()

# Allow running headless from the command line
if (args.fig == False):
    matplotlib.use("agg")

t0x_file_pat = args.pattern

# parse record 98 and build the x and y values where
# x values is GPS time and y is delta time
# compared to previous record of same time
def extract_first_gps_time_with_valid_mss_snr(d):
    i = 0
    firstGpsTime = 0

    while i < len(d): 

        time = d[i][1]
        freq = d[i][2]
        band = d[i][3]
        snr = d[i][4]

        if (snr > 0 and freq > 0 and band > 0):
            firstGpsTime = time
            break

        i += 1

    return firstGpsTime


# plot out times to first record 98 since first fix
def plot_times_to_first_valid_mss_data( deltaTimes, failedTimes, plot_label ):

    if len(deltaTimes) == 0:
        return

    indices = []
    failedCounter = 0

    for i in range(0, len(deltaTimes), 1):
        indices.append(i)

    for failedTime in failedTimes:
        if np.isnan(failedTime) == False:
            failedCounter += 1

    print("size = %d" % len(indices))

    fig = m.figure()    
    ax = fig.add_subplot(1, 1, 1)
    m.plot( indices, deltaTimes, marker='x', linestyle='dashed', linewidth=0.5, label='Time' )
    m.plot( indices, failedTimes, marker='x', linestyle='none', color='r', label='Failed' )

    ax.yaxis.grid(True, which='minor', linestyle=':', color='lightgrey')
    ax.yaxis.set_major_formatter(FormatStrFormatter("%.0f"))
    #ax.yaxis.set_major_locator(MultipleLocator(5))
    #ax.yaxis.set_minor_locator(MultipleLocator(1))

    ax.xaxis.set_major_formatter(FormatStrFormatter("%d"))
    #ax.yaxis.set_minor_locator(MultipleLocator(1))
    #ax.xaxis.set_major_locator(MultipleLocator(1))
    
    yMin, yMax = fig.gca().get_ylim()
    fig.gca().set_ylim(0, yMax + 5 )

    m.annotate('Count: %d\nMean: %.0fs\nMax: %.0fs\nMin: %.0fs\nFailed: %d' \
        % (len(deltaTimes), np.nanmean(deltaTimes), np.nanmax(deltaTimes), np.nanmin(deltaTimes), failedCounter), 
        xy=(0.95, 0.05), 
        xycoords='axes fraction', horizontalalignment='right', 
        verticalalignment='bottom')

    if plot_label == None:
        m.title("Rec 33:4 Time to first valid MSS since first pos fix")
    else:
        m.title("Rec 33:4 Time to first valid MSS since first pos fix\n[" + plot_label + "]")
    
    m.xlabel('Index')
    m.ylabel('Time (seconds)')

    m.grid(True)
    m.legend(loc='best')
    m.tight_layout()

    if (args.fig == True):
        m.show()
    else:
        pngName = 'rec33-4_Mss_multi_plot.png'
        m.savefig(pngName)
        print('saved %s' % pngName)

    return

deltaTimes = []
failedTimes = []
csvData = []
csvData.append("FileName,FirstPosSecond,FirstMSSSecond,TimeToMSSFromPos")

for filename in sorted(glob.glob(t0x_file_pat)):
    
    #print("Processing %s" % filename)
    (ref,k)=m.vd2arr(filename,rec='-d35:2')
    d=m.cmd2arr("VIEWDAT.exe -d33:4 -mb \"" + filename + "\"")

    firstPosTime = ref[:,k.TIME][0] #time of first position fix   
    lastPosTime = ref[:,k.TIME][-1]
    totalPosTime = lastPosTime - firstPosTime
    firstValidMssTime = extract_first_gps_time_with_valid_mss_snr(d)
    
    #No valid Mss? use total pos duration instead
    if (firstValidMssTime == 0):
        deltaTime = totalPosTime  #use totalPosTime to get more accurate stats
        failedTime = totalPosTime
    else:
        deltaTime = firstValidMssTime - firstPosTime
        failedTime = np.nan

    #use 0 if negative
    if (deltaTime < 0):
        deltaTime = 0

    deltaTimes.append(deltaTime)
    failedTimes.append(failedTime)

    csvData.append("%s,%d,%s,%s" % (os.path.basename(filename), \
        firstPosTime, \
        "" if firstValidMssTime == 0 else str(firstValidMssTime), \
        "" if firstValidMssTime == 0 else str(deltaTime)))

    #print("%d,%d,%d,%d" % (len(deltaTimes), firstPosTime, firstValidMssTime, firstValidMssTime - firstPosTime))


plot_times_to_first_valid_mss_data(deltaTimes, failedTimes, args.label)
#plot_record33_4(d, args.filename, 'IQ', 5)

#write times out to CSV file if enabled
if (args.csv == True):
    with open('rec33-4_Mss_multi_plot.csv', 'w') as f:
        for item in csvData:
            f.write("%s\n" % item)
        print('saved %s' % f.name)