#!/usr/bin/python
"""
    mahali_log_plotter.py

    $Id: mahali_log_plotter.py 476 2015-08-13 21:20:35Z flind $

    This software reads mahali sensor and status logs files. It then produces a
    plot which summarizes parameter values versus time and can flags particular event
    intervals.

"""

import time
import sys
import os
import optparse
import traceback
import numpy
import datetime
import json
import glob
import matplotlib
import matplotlib.pylab
import matplotlib.dates

import mahali_common

DEBUG = False

def load_jsonl_data(dpath):
    fnames = glob.glob(dpath + '/*.jsonl')

    fnames.sort()

    objs = []

    for f in fnames:
        fid = open(f,'r')

        for l in fid:
            try:
                d = mahali_common.deserialize_json(l)
                objs.append(d)
            except:
                pass

        fid.close()

    return objs


def json2array(data, filter, verbose):

    dobj = {}

    for d in data:

        if verbose:
            print d

        if 'event' in d:

            try:
                evt_val = d['event_type']
            except:
                if verbose:
                    print "no event value in ", d

            try:
                evd_val = d['event_data']
            except:
                if verbose:
                    print "no event data in ", d

            if evt_val in filter:
                ev_val = evt_val
            elif evd_val in filter:
                ev_val = evd_val

            if evt_val in filter or evd_val in filter:

                if ev_val in dobj:
                    dtime = d['unix_time']
                    nd = numpy.array([[dtime],[True]],ndmin=2)
                    dobj[ev_val] = numpy.hstack((dobj[ev_val],nd))
                else:
                    dtime = d['unix_time']
                    nd = numpy.array([[dtime],[True]],ndmin=2)
                    dobj[ev_val] = numpy.array([[dtime],[1]],ndmin=2)

            if verbose and evd_val in filter:
                print evd_val

            if verbose and evt_val in filter:
                print evt_val

        elif 'measurement_type' in d:
            m_tval = d['measurement_type']
            if m_tval in filter:
                if m_tval in dobj:
                    dtime = d['measurement_time']
                    dval = d['data']
                    nd = numpy.array([[dtime],[dval]],ndmin=2)
                    dobj[m_tval] = numpy.hstack((dobj[m_tval],nd))
                else:
                    dtime = d['measurement_time']
                    dval = d['data']
                    dobj[m_tval] = numpy.array([[dtime],[dval]],ndmin=2)

                #print dtime, dval
        else:
            print d

    if verbose:
        print dobj

    return dobj


def parse_command_line():
    parser = optparse.OptionParser()
    parser.add_option("-v", "--verbose",action="store_true", dest="verbose", default=False,help="Print message details.")
    parser.add_option("-i", "--input",dest="ipath",help="Input directory path.")
    parser.add_option("-p", "--parameter",action="append",dest="parms",help="Plot a specific parameter type.")
    parser.add_option("-o", "--output",dest="ofile",help="Output plot to the provided file name.")
    parser.add_option("-t", "--title",dest="title",help="Title for plot")
    parser.add_option("-r", "--retain",action="store_true",dest="retain",default=False,help="Combine output on a single plot panel.")

    (options, args) = parser.parse_args()

    return (options, args)


input_path = "./"
parameter_list = []

if __name__ == '__main__':

    options, args = parse_command_line()

    if options.ipath:
        input_path = options.ipath

    if options.parms:
        parameter_list = options.parms
    else:
        print "A minimum of one plot parameter type is required (e.g. -p temperature)."
        sys.exit()

    # parse command line options
    options, args = parse_command_line()

    data_json = []

    # get all the data in the path
    try:
        t_data_json = load_jsonl_data(input_path + '/sensor')
        data_json.extend(t_data_json)
    except:
        print "problem loading ", input_path, '/sensor'
        traceback.print_exc(limit=1, file=sys.stdout)

    try:
        t_data_json = load_jsonl_data(input_path + '/command')
        data_json.extend(t_data_json)
    except:
        print "problem loading ", input_path, '/command'
        traceback.print_exc(limit=1, file=sys.stdout)

    try:
        t_data_json = load_jsonl_data(input_path + '/status')
        data_json.extend(t_data_json)
    except:
        print "problem loading ", input_path, '/status'
        traceback.print_exc(limit=1, file=sys.stdout)

    try:
        t_data_json = load_jsonl_data(input_path + '/error')
        data_json.extend(t_data_json)
    except:
        print "problem loading ", input_path, '/error'
        traceback.print_exc(limit=1, file=sys.stdout)

    try:
        t_data_json = load_jsonl_data(input_path + '/info')
        data_json.extend(t_data_json)
    except:
        print "problem loading ", input_path, '/info'
        traceback.print_exc(limit=1, file=sys.stdout)

    try:
        t_data_json = load_jsonl_data(input_path + '/debug')
        data_json.extend(t_data_json)
    except:
        print "problem loading ", input_path, '/debug'
        traceback.print_exc(limit=1, file=sys.stdout)


    # convert to a dictionary of arrays

    dset = json2array(data_json, parameter_list, options.verbose)


    # plot parameter types with type specific output one per subplot

    nplot = 1

    fig = matplotlib.pyplot.figure()

    color_set = ['k','b','g','r','c','m']

    ylbl = ''

    for p in dset:
        #print p
        if options.retain:
            ax = matplotlib.pyplot.subplot(1,1,1)
            color = color_set[(nplot % len(color_set))-1]
        else:
            ax = matplotlib.pyplot.subplot(len(dset),1,nplot)
            color = 'k'

        nplot = nplot + 1
        tval = dset[p][0]
        tval = [datetime.datetime.fromtimestamp(eachDate) for eachDate in tval]

        dval = dset[p][1]

        if dval[0] == True:
            ln, = ax.plot(tval,dval*nplot,'%sD' % (color))

        else:
            ln, = ax.plot(tval,dval,'%s.' % (color))
            ylbl = ylbl + ' ' + p

        ln.set_label(p)

        ax.xaxis.set_major_formatter(matplotlib.dates.DateFormatter('%Y-%m-%d %H:%M:%S'))
        matplotlib.pyplot.xlabel('time')

        matplotlib.pyplot.grid()


        if options.title:
            matplotlib.pyplot.title(options.title)


    # render plot
    fig.autofmt_xdate()

    matplotlib.pyplot.ylabel(ylbl)

    matplotlib.pyplot.legend(fontsize='xx-small')
    #matplotlib.pyplot.autofmt_xdate()

    matplotlib.pyplot.show()

    # output to efile if needed
    if options.ofile:
        pass
