#!/usr/bin/env python
"""
Check mongo collections for at least one recent record, and print a message saying which (if any) are stale.
Set of collections to check is taken from a "metadata" collection specified by arguments
"""
from datetime import datetime, timedelta
import os, sys
import pymongo

def say(msg):
    sys.stdout.write(msg)
    sys.stdout.write("\n")

def error(msg):
    sys.stderr.write("ERROR: ")
    sys.stderr.write(msg)
    sys.stderr.write("\n")

def usage():
    x = {'program' : os.path.basename(sys.argv[0])}
    print "usage: %(program)s {metadata-db-name} {metadata-collection-name} {age-in-hours}" % x
    sys.exit(2)

def run(args=None):
    try:
        i = 0
        if args is None:
           args = sys.argv[1:]
        meta_db,meta_coll,age = args
        dt = datetime.now() - timedelta(hours=int(age))
    except (IndexError, ValueError), err:
        usage()
    dt=dt.replace(microsecond=0);
    conn = pymongo.Connection(host='localhost')
    meta=conn[meta_db][meta_coll]
    messages=[]
    for to_check in meta.find():
        message=check(conn, to_check['db'], to_check['coll'], to_check['ts_field'], dt);
        if message:
            messages.append(message)
    if messages:
        say('The most recent entry in each the following collections is more than %s hours old:' % (age))
        say('')
        prettyPrint(messages, dt)
    return len(messages)

def check(conn, db_name, coll_name, dt_field, dt):
    coll=conn[db_name][coll_name]
    result = coll.find_one({dt_field : { '$gt' : dt } })
    if result is None:
        result2 = coll.find_one(fields={dt_field:1,'_id':0},sort=[(dt_field,-1)])
        if result2 is None:
            return (coll.full_name,None)
        if(dt_field.find('.')==-1):
            ts=result2[dt_field]
        else:
            dtfs=dt_field.split('.')
            ts=result2[dtfs[0]][dtfs[1]]
#        if type(ts) is unicode:
#            # stopgap to handle string-encoded timestamps
#            ts=dt #datetime.strptime(ts,"%a %b %d %X %Z %Y")
        #return("%s.%s\t%s (%s %s)" % (db_name, coll_name, result2, type(ts), ts))
        return (coll.full_name,ts.replace(microsecond=0))
    # else return None

def prettyPrint(messages, dt):
    format = "%%-%ds  %%-19s  %%-s" % (max([len(m[0]) for m in messages]))
    say(format % ("Source","Last (UTC)","Age"))
    for m in messages:
        if m[1] is None:
            age='-'
        else:
            age=( dt - m[1] )
        say(format % (m[0], m[1], age))

if __name__ == '__main__':
    try:
        sys.exit(run())
    except Exception, err:
        error(str(err))
        sys.exit(-1) 
