#!/usr/bin/python

# tz_geonames.py
#       --copyright--                   Copyright 2007 (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--
#       December 25, 2007       bar
#       May 17, 2008            bar     email adr
#       June 13, 2009           bar     don't fuss if there is no info in main
#       November 29, 2011       bar     pyflake cleanup
#       May 27, 2012            bar     doxygen namespace
#       --eodstamps--
##      \file
#       \namespace              tzpython.tz_geonames
#
#
#       Get information from Geonames (just did not feel like messing with geoname.py to get radius and timezone and FULL and so on)
#
#       Note:
#
#           sws.geonames.org/...ID.../about.rdf     gets an ID's information
#                                    /nearby.rdf    is documented way to do findNearby, sort of
#
#


import  xml.dom.minidom

import  latlon
import  tz_gps
import  url_getter




numeric_tags    = [
                    "lat",
                    "lng",
                    "population",
                    "elevation",
                    "distance",

                    "dstOffset",
                    "gmtOffset",

                    "geonameId"
                  ]

dupe_tags       = {
                    'lng'       :   'lon',
                    'elevation' :   'altitude',
                  }



class   a_location(object) :

    def __init__(me, geoname_el) :

        me.tags = {}

        for el in geoname_el.childNodes :
            if  el.nodeName :
                val                         = tz_gps.inner_text(el)
                me.tags[    el.nodeName]    = val
                setattr(me, el.nodeName,      val)
            pass

        for k in numeric_tags :
            v   = None
            if  k in me.tags :
                v       = me.tags[k]
                if  v   :
                    v   = float(v)
                else :
                    v   = None
                pass

            me.tags[k]  = v
            setattr(me, k, v)

        for t in dupe_tags.keys() :
            if  (t in me.tags) and (dupe_tags[t] not in me.tags) :
                me.tags[    dupe_tags[t]]   = me.tags[t]
                setattr(me, dupe_tags[t],     me.tags[t])
            pass

        pass


    def to_a_point(me) :
        return(tz_gps.a_point(name = me.name, lat = me.lat, lon = me.lng, altitude = me.elevation))


    def __str__(me) :
        s   = ""

        kys = me.tags.keys()

        nk  = "name"
        if  nk in kys :
            s  += "%s=%s\n" % ( nk, me.tags[nk] )

        kys.sort()

        for k in kys :
            if  (k != "#text") and (k != nk) and (k != "lon") and (k != "altitude") :
                s  += "%s=%s\n" % ( k, me.tags[k] )
            pass

        return(s)


    pass        # a_location



"""
    http://ws.geonames.org/findNearby?lat=47.36121&lng=-122.02039&style=FULL&radius=0.2

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <geonames>
    <geoname>
    <name>Summit</name>
    <lat>47.3612122</lat>
    <lng>-122.020393</lng>
    <geonameId>5812510</geonameId>
    <countryCode>US</countryCode>
    <countryName>United States</countryName>
    <fcl>P</fcl>

    <fcode>PPL</fcode>
    <fclName>city, village,...</fclName>
    <fcodeName>populated place</fcodeName>
    <population/>
    <alternateNames>4 Corners</alternateNames>
    <elevation>166</elevation>
    <adminCode1>WA</adminCode1>
    <adminName1>Washington</adminName1>
    <adminCode2>033</adminCode2>

    <adminName2>King County</adminName2>
    <distance>0.0003</distance>
    </geoname>
    <geoname>
    <name>4 Corners Safeway</name>
    <lat>47.3603317796418</lat>
    <lng>-122.018328309059</lng>
    <geonameId>6620511</geonameId>
    <countryCode>US</countryCode>
    <countryName>United States</countryName>

    <fcl>S</fcl>
    <fcode>MKT</fcode>
    <fclName>spot, building, farm</fclName>
    <fcodeName>market</fcodeName>
    <population/>
    <alternateNames/>
    <elevation>170</elevation>
    <adminCode1>WA</adminCode1>
    <adminName1>Washington</adminName1>
    <adminCode2/>

    <adminName2/>
    <distance>0.1834</distance>
    </geoname>
    </geonames>
"""

def get_nearby(lat, lon, radius_in_nautical_miles = None) :
    """ Return an array of a_location's containing places and features near to the given lat/lon. """

    rs      = ""
    if  radius_in_nautical_miles :
        rs  = "&radius=%f" % ( radius_in_nautical_miles * latlon.metersPerNauticalMile / 1000.0 )

    qs      = "lat=%f&lng=%f&style=FULL%s" % ( float(lat), float(lon), rs )

    r       = url_getter.url_open_read_with_timeout("http://ws.geonames.org/findNearby?" + qs, timeout = 10.0)

    if  not r  :
        return(None)

    dom = xml.dom.minidom.parseString(r)

    gns = dom.getElementsByTagName("geoname")

    la  = []
    for gn in gns :
        la.append(a_location(gn))

    return(la)





"""
    http://ws.geonames.org/timezone?lat=47.60611111&lng=-122.33194444

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <geonames>
    <timezone>
    <countryCode>US</countryCode>
    <countryName>United States</countryName>
    <lat>47.60611111</lat>
    <lng>-122.33194444</lng>
    <timezoneId>America/Los_Angeles</timezoneId>
    <dstOffset>-7.0</dstOffset>
    <gmtOffset>-8.0</gmtOffset>

    </timezone>
    </geonames>
"""

def get_timezone(lat, lon) :
    """ Return the timezone offset DST and standard time for a given lat/lon. """

    qs      = "lat=%f&lng=%f" % ( float(lat), float(lon) )

    r       = url_getter.url_open_read_with_timeout("http://ws.geonames.org/timezone?" + qs, timeout = 10.0)

    if  not r  :
        return(None)

    dom = xml.dom.minidom.parseString(r)

    tz  = dom.getElementsByTagName("timezone")

    if  not tz :
        return(None)

    tz  = a_location(tz[0])

    return(tz)



#
#
#
if __name__ == '__main__' :
    import  sys

    import  TZCommandLineAtFile

    del(sys.argv[0])

    TZCommandLineAtFile.expand_at_sign_command_line_files(sys.argv)

    while len(sys.argv) :
        lls         = sys.argv.pop(0)
        ( lat, lon) = latlon.parse_lat_lon(lls)

        if  lat == None :
            print "I cannot understand", lls
        else :
            tz  = get_timezone(lat, lon)
            print "timezone:"
            print tz

            nb      = get_nearby(lat, lon, 1)
            nb      = nb or []
            for l in nb :
                print l
                p   = l.to_a_point()
                print p
            pass
        pass

    pass



#
#
#
# eof
