#!/usr/bin/env python

"""Script to plot h(t) triggers for some epoch
"""

__author__ = "Duncan Macleod <duncan.macleod@ligo.org>"

import argparse
import os
import re
from collections import OrderedDict
from configparser import DEFAULTSECT

from matplotlib import use
use('Agg')  # noqa

from gwpy.time import to_gps

from gwsumm import globalv
from gwsumm.archive import (write_data_archive, read_data_archive)
from gwsumm.config import GWSummConfigParser
from gwsumm.data import get_timeseries
from gwsumm.state import generate_all_state
from gwsumm.tabs import GuardianTab

GWSummConfigParser.OPTCRE = re.compile(
    r'(?P<option>[^=\s][^=]*)\s*(?P<vi>[=])\s*(?P<value>.*)$')


def safe_eval(val):
    """Evaluate the given string as a line of python, if possible

    If the :meth:`eval` fails, a `str` is returned in stead.
    """
    try:
        return eval(val)
    except (NameError, SyntaxError):
        return str(val)


# -----------------------------------------------------------------------------
# Read command line

parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('node')
parser.add_argument('gpsstart', type=to_gps)
parser.add_argument('gpsend', type=to_gps)
parser.add_argument('config', help='config-file defining guardian node')
parser.add_argument('-i', '--ifo', type=str, default='L1')
parser.add_argument('-s', '--section', type=str,
                    help='suffix of INI tab section to read, e.g. give '
                         '--section=\'ISC_LOCK\' to read [tab-ISC_LOCK] '
                         'section, defaults to {node}')
parser.add_argument('-t', '--epoch', type=to_gps,
                    help='Zero-time for plot, defaults to GPSSTART')
parser.add_argument('-p', '--plot-params', action='append', default=[],
                    help='extra plotting keyword argument')
parser.add_argument('-m', '--multi-process', type=int, default=1,
                    dest='nproc',
                    help='number of processes to use, default: %(default)s')
parser.add_argument('-o', '--output-file', default='trigs.png',
                    help='output file name, default: %(default)s')
parser.add_argument('-v', '--verbose', action='store_true',
                    help='print verbose output, default: False')
parser.add_argument('-P', '--profile', action='store_true',
                    help='print timing output, default: False')
archopts = parser.add_mutually_exclusive_group()
archopts.add_argument('-a', '--archive',
                      help='full path of HDF archive for data')
archopts.add_argument('-r', '--read-only-archive',
                      help='full path of HDF archive for data, does not write')

args = parser.parse_args()
if args.epoch is None:
    args.epoch = args.gpsstart
globalv.VERBOSE = args.verbose
globalv.PROFILE = args.profile
state = generate_all_state(args.gpsstart, args.gpsend)

# format params
params = {}
for input_ in args.plot_params:
    key, val = input_.split('=', 1)
    params[key.strip('-')] = safe_eval(val)

# read config
config = GWSummConfigParser(dict_type=OrderedDict)
config.read([args.config])
config.set(DEFAULTSECT, 'gps-start-time', str(int(args.gpsstart)))
config.set(DEFAULTSECT, 'gps-end-time', str(int(args.gpsend)))
config.set(DEFAULTSECT, 'IFO', args.ifo)
sec = 'tab-%s' % (args.section or args.node)

# read archive
if args.archive and not args.read_only_archive:
    args.read_only_archive = args.archive
if args.read_only_archive and os.path.isfile(args.read_only_archive):
    read_data_archive(args.read_only_archive)
    print("Read data archive from {0.read_only_archive}".format(args))

# make tab
tab = GuardianTab.from_ini(config, sec, mode='gps', path='.', plotdir='.')
tab.plots = tab.plots[:1]
tab.plots[0].pargs.update(params)
tab.plots[0].pargs['epoch'] = args.epoch

# process
print("Processing:")
tab.process(nproc=args.nproc)
plotfile = tab.plots[0].outputfile
os.rename(plotfile, args.output_file)
print('Plot saved to {0.output_file}'.format(args))

# crop and save archive
if args.archive:
    for channel in globalv.DATA:
        globalv.DATA[channel] = get_timeseries(channel, state, query=False)
    write_data_archive(args.archive)
    print("Archive recorded as {0.archive}".format(args))
