#!/usr/bin/env python
# coding: utf-8
"""\
usage: ntploggps [-h] [-o] [-l LOGFILE] [-v] [-V]

gpsd log file generator

optional arguments:
  -h, --help            show this help message and exit
  -l LOGFILE, --logfile LOGFILE
                        append log data to LOGFILE instead of stdout
  -o, --once            log one line, then exit
  -w WAIT, --wait WAIT  wait WAIT seconds after each log line, default 5
  -v, --verbose         be verbose
  -V, --version         show program's version number and exit

See the manual page for details.
"""

from __future__ import print_function

import io
import sys
import threading
import time

try:
    import gps
    import ntp.util
except ImportError as e:
    sys.stderr.write("ntploggps: can't find Python NTP modules "
                     "-- check PYTHONPATH.\n")
    sys.stderr.write("%s\n" % e)
    sys.exit(1)

try:
    import argparse
except ImportError:
    sys.stderr.write("""
ntpologgps: can't find the Python argparse module
         If your Python version is < 2.7, then manual installation is needed:
         # pip install argparse
""")
    sys.exit(1)


parser = argparse.ArgumentParser(description="gpsd log file generator",
                                 epilog="""
See the manual page for details.
""")

parser.add_argument('-l', '--logfile',
                    dest='logfile',
                    help="append log data to LOGFILE instead of stdout",
                    nargs=1)

parser.add_argument('-o', '--once',
                    action="store_true",
                    dest='once',
                    help="log one line, then exit")

parser.add_argument('-w', '--wait',
                    default=[5],
                    dest='wait',
                    help="wait WAIT seconds after each log line, default 5",
                    nargs=1,
                    type=int)

parser.add_argument('-v', '--verbose',
                    action="store_true",
                    dest='verbose',
                    help="be verbose")

parser.add_argument('-V', '--version',
                    action="version",
                    version="ntploggps %s" % ntp.util.stdversion())

args = parser.parse_args()

if args.verbose:
    print("ntploggps: arguments:")
    print(args)

if args.logfile:
    # log to logfile
    try:
        out = open(args.logfile[0], mode='a')
    except io.UnsupportedOperation as e:
        sys.stderr.write("ntploggps: can't open logfile %s\n" % args.logfile)
        sys.stderr.write("%s\n" % e)
        sys.exit(1)

    if args.verbose:
        print("ntploggps: opened log file %s" % args.logfile[0])

else:
    # log to stdout
    out = sys.stdout


class GpsPoller(threading.Thread):
    running = False       # True when thread is running. Quit when set False

    def __init__(self):
        threading.Thread.__init__(self)
        # start the streaming of gps data
        try:
            self.gpsd = gps.gps(mode=gps.WATCH_ENABLE)
        except BaseException as e:
            sys.stderr.write("ntploggps: Can't connect to gpsd, %s\n"
                             "         Is gpsd running?\n" % e)
            sys.exit(1)
        self.running = True

    def run(self):
        while gpsp.running:
            try:
                self.gpsd.next()     # loop and grab each set of gpsd info
            except:
                self.running = False
                break

    def get_time(self):
        "Return the gpsd time fix"
        return self.gpsd.fix.time

    def display(self):
        "Displays the time, device, TDOP, and nSat data collected"
        out.write('%s %s %f %d\n' % (gps.isotime(self.get_time()),
                                     self.gpsd.device,
                                     self.gpsd.tdop,
                                     self.gpsd.satellites_used))

if __name__ == '__main__':
    # this is the main thread
    if args.verbose:
        print("ntploggps: creating poll thread")

    gpsp = GpsPoller()    # create the thread
    try:
        gpsp.start()      # start it up
        last_time = 0
        out.write("\n")         # print blank line to prevent log corruption
        out.write("# Time       Device     TDOP     nSat\n")
        while gpsp.running:
            # It may take a second or two to get good data

            try:
                if 'nan' != gpsp.get_time() and not gps.isnan(gpsp.get_time()):
                    if last_time != gpsp.get_time():
                        gpsp.display()
                        out.flush()
                    last_time = gpsp.get_time()
                    if args.once:
                        # just once
                        break

            except AttributeError as e:
                print('parse error\n')

            # wait a bit before next log
            time.sleep(args.wait[0])

    except (KeyboardInterrupt, SystemExit):    # when you press ctrl+c
        args.once = True        # stop the retry loop
        if args.verbose:
            print("\nKilling Thread...")
        else:
            # print a blank line to make bash happy
            print("")
    except Exception as e:       # any error, signal
        print(e)

    # tell the thread to die
    gpsp.running = False

    # wait for the thread to finish what it's doing
    gpsp.join()

    if args.verbose:
        print("ntploggps: Done -- Exiting.")

    # mom says: be nice and flush
    out.flush()
    out.close()
