#!/usr/bin/python

# near_gps_files.py
#       --copyright--                   Copyright 2010 (C) Tranzoa, Co. All rights reserved.    Warranty: You're free and on your own here. This code is not necessarily up-to-date or of public quality.
#       --url--                         http://www.tranzoa.net/tzpython/
#       --email--                       pycode is the name to send to. tranzoa.com is the place to send to.
#       --bodstamps--
#       November 7, 2010
#       November 29, 2011       bar     pyflake cleanup
#       --eodstamps--
#
#       Tell track files with a point nearest to the given point.
#
#

import  sys

import  tz_gps


help_str    = """
python  %s   (options)   "lat,lon"  ambiguous_input_files.gpx_nmea

    Tell input files with points closest to the given point.

Options:

    --max_files     n           Report the nearest 'n' files, only                (default: 1).
    --flat                      Use flat distance rather than including altitude.
    --ignore        file_name   Do not check the given file.
    --file_since    date/time   Only input files dated since the given date/time  (default: year 1970).
    --file_before   date/time   Only input files dated before the given date/time (default: year 2038).
    --sub_dirs                  Look for files of given names in sub-directories  (and --ignore files, too).
    --verbose                   Increase the verbosity (to see better files as they are found).

"""


def closest_point_in_file(point, fn, flat = False) :
    rtn = point.flat_distance_from if flat else point.distance_from

    ta  = tz_gps.tracks_from_file(fn)

    bp  = None
    bd  = sys.maxint
    for t in ta :
        for p in t.points :
            d   = rtn(p)
            if  bd  > d :
                bd  = d
                bp  = p
            pass
        pass

    return(bp)



def closest_points_by_file(point, fns, flat = False, verbose = 0) :
    rtn = point.flat_distance_from if flat else point.distance_from

    if  not isinstance(fns, (tuple, list)) :
        fns     = [ fns ]

    fls         = {}
    bd          = sys.maxint
    for fn in fns :
        fls[fn] = closest_point_in_file(point, fn, flat)
        if  verbose :
            p       = fls[fn]
            d       = rtn(p)
            if  bd  > d :
                bd  = d
                print fn, d, p
            pass
        pass

    return(fls)


def sort_files_by_closest_point(point, fns, flat = False, verbose = 0) :
    rtn = point.flat_distance_from if flat else point.distance_from

    if  not isinstance(fns, (tuple, list)) :
        fns = [ fns ]

    fls     = closest_points_by_file(point, fns, flat = flat, verbose = verbose)

    da      = {}
    for fn in fls.keys() :
        da[fn]  = rtn(fls[fn])

    fns.sort(lambda a, b : cmp(da[a], da[b]))

    return(fls, da)



if  __name__ == '__main__' :
    import  os

    import  TZCommandLineAtFile
    import  latlon
    import  tz_parse_time
    import  tzlib


    program_name    = sys.argv.pop(0)
    TZCommandLineAtFile.expand_at_sign_command_line_files(sys.argv)

    flat            = False
    excludes        = []
    file_before     = float(sys.maxint)
    file_since      = float(0)
    do_sub_dirs     = False
    max_files       = 1
    verbose         = 0


    while True :
        oi  = tzlib.array_find(sys.argv, [ "--help", "-h", "-?", "/h", "/H", "/?" ] )
        if  oi < 0 :    break
        del sys.argv[oi]
        print help_str % os.path.basename(program_name)
        sys.exit(254)


    while True :
        oi  = tzlib.array_find(sys.argv, [ "--verbose", "--show_info", "--show-info", "--showinfo", ] )
        if  oi < 0  :    break
        del sys.argv[oi]
        verbose    += 1


    while True :
        oi  = tzlib.array_find(sys.argv, [ "--flat", "-f", ] )
        if  oi < 0  :    break
        del sys.argv[oi]
        flat        = True


    while True :
        oi  = tzlib.array_find(sys.argv, [ "--max_files", "--max-files", "--maxfiles", "-m", "-c", ] )
        if  oi < 0  :    break
        del sys.argv[oi]
        max_files   = max(int(sys.argv.pop(oi)), 1)


    while True :
        oi  = tzlib.array_find(sys.argv, [ "--ignore" ] )
        if  oi < 0 :    break
        del sys.argv[oi]
        excludes.append(tzlib.ambiguous_file_list(sys.argv.pop(oi), do_sub_dirs = do_sub_dirs))


    while True :
        oi  = tzlib.array_find(sys.argv, [ "--file_since", "--file-since", "--filesince", "-s", "-a", ] )
        if  oi < 0 :    break
        del sys.argv[oi]
        file_since              = tz_parse_time.parse_time(sys.argv.pop(oi))
        if  file_since         == None :
            print "I cannot understand the file_since!"
            sys.exit(102)
        pass


    while True :
        oi  = tzlib.array_find(sys.argv, [ "--file_before", "--file-before", "--filebefore", "-b", ] )
        if  oi < 0 :    break
        del sys.argv[oi]
        file_before             = tz_parse_time.parse_time(sys.argv.pop(oi))
        if  file_before        == None :
            print "I cannot understand the file_before!"
            sys.exit(102)
        pass


    ifns    = {}
    for fn in excludes :
        ifns[os.path.abspath(fn)]   = True


    if  len(sys.argv) < 2 :
        print "I need a lat,lon and at least 1 file to check!"
        sys.exit(103)


    lls             = sys.argv.pop(0)
    ( lat, lon )    = latlon.parse_lat_lon(lls)
    p               = tz_gps.a_point(lat = lat, lon = lon)

    fns     = {}
    for afn in sys.argv :
        fls = tzlib.ambiguous_file_list(afn)
        for fn in fls :
            fn  = os.path.abspath(fn)
            if  fn not in ifns :
                if  file_since <= os.path.getmtime(fn) < file_before :
                    fns[fn] = True
                pass
            pass
        pass

    if  not fns :
        print >>sys.stderr, "No file found!"
        sys.exit(104)


    fns = fns.keys()

    fts = {}
    for fn in fns :
        fts[fn] = os.path.getmtime(fn)

    fns.sort(lambda a, b : cmp(fts[a], fts[b]))

    ( flps, flds )  = sort_files_by_closest_point(p, fns, flat = flat, verbose = verbose)

    for i in xrange(min(max_files, len(fns))) :
        fn          = fns[i]
        print fn, flds[fn]
        print " ", flps[fn]

    pass


#
#
# eof

