#!/usr/bin/python
# -*- python -*-

import os
import sys
import re
import readline
import atexit
import time
import urllib, urllib2
import json
import operator
import subprocess
from optparse import OptionParser
from smap.archiver import settings

HISTFILE = os.path.expanduser('~/.smap-query-history')

def stringify_times(obj):
    for v in obj:
        if 'Readings' in v:
            for i in xrange(0, len(v['Readings'])):
                v['Readings'][i][0] = time.ctime(v['Readings'][i][0]/1000)

def run_query(opts, q):
    try:
        query = {}
        if opts.key:
            query['key'] = opts.key.split(',')
            if opts.private:
                query['private'] = ['']

        qurl = opts.url + '?' + urllib.urlencode(query, doseq=True)
        if opts.verbose > 0:
            print >>sys.stderr, qurl
            print >>sys.stderr, q

        if q.strip().startswith("plot"):
            q = q.strip()[5:]
            doplot = True
        elif q.strip().startswith("gp"):
            add_gnuplot(q.strip()[3:])
        else:
            doplot = False

        tic = time.time()
        fp = urllib2.urlopen(qurl, data=q, timeout=opts.timeout)
        obj = json.load(fp)
        toc = time.time()

        if doplot:
            plot(obj)
        else:
            if opts.dates:
                stringify_times(obj)

            json.dump(obj, sys.stdout, sort_keys=True, indent=2)
            print # add a newline
        print >>sys.stderr, "%i (%i ms)" % (len(obj), int((toc - tic) * 1000))

    except urllib2.HTTPError, e:
        print >>sys.stderr, "ERROR:", e.read()
    except urllib2.URLError, e:
        print >>sys.stderr, "ERROR:", e
        raise StopIteration()

gnuplot_args = [["set", "xdata", "time"],
                ["set", "timefmt", '"%s"'],
                ["set", "term", "dumb"],
                ["unset", "key"]]
def get_gnuplot():
    return '\n'.join(map(' '.join, gnuplot_args))

def set_gnuplot(cmd):
    cmd = cmd.trim().split(" ")

def plot(dat):
    pfile = '/tmp/smap-query.%i.pfile' % os.getpid()
    pscript = '/tmp/smap-query.%i.pscript' % os.getpid()
    # write the data file
    dvecs = map(operator.itemgetter("Readings"), dat) 
    def getpoint(d):
        if len(d) > 0: return d[0]
        else: 0xffffffff * 1000

    with open(pfile, "w") as fp:
        while sum((len(x) for x in dvecs)):
            ts = min(map(operator.itemgetter(0),
                         map(getpoint, dvecs)))
            line = []
            for i in xrange(0, len(dvecs)):
                if dvecs[i][0][0] == ts:
                    line.append(dvecs[i][0][1])
                    del dvecs[i][0]
                else:
                    line.append(float("NaN"))
            print >>fp, ts, ' '.join(map(str, line))
    with open(pscript, "w") as fp:
        print >>fp, get_gnuplot()
        print >>fp, """
plot %s
    """ % ','.join(['"%s" using ($1/1000):%i' % (pfile, x+2) for x in xrange(0, len(dat))])

    with open('/dev/null', 'w') as null:
        p = subprocess.Popen("gnuplot %s" % pscript, 
                             shell=True, stderr=null)
    rc = p.wait()
    if rc == 127:
        print "ERROR: could not find gnuplot in $PATH; is it installed?"
    
    os.remove(pfile)
    os.remove(pscript)

if __name__ == '__main__':
    usage = 'usage: %prog [options] querys ...'
    parser = OptionParser(usage=usage)
    parser.add_option('-u', '--url', dest='url', 
                      default="http://new.openbms.org/backend/api/query",
                      help='location of backend server')
    parser.add_option('-k', '--key', dest='key', default=None,
                      help='api keys: k1[,k2 ...]')
    parser.add_option('-p', '--private', dest='private', default=False,
                      help='display only results associated with the api key',
                      action='store_true')
    parser.add_option('-t', '--timeout', dest='timeout', default=10,
                      type="int")
    parser.add_option('-v', dest='verbose', default=0,
                      help="be verbose", action="count")
    parser.add_option('-n', '--no-dates', dest='dates',
                      default=True, action='store_false',
                      help='don\'t convert dates to string representation')
    opts, args = parser.parse_args()

    if len(args) > 0:
        map(lambda x: run_query(opts, x), args)
    elif not os.isatty(sys.stdin.fileno()):
        q = sys.stdin.read()
        run_query(opts, q)
    else:
        print >>sys.stderr, "Querying", opts.url
        readline.parse_and_bind('tab: complete')
        readline.parse_and_bind('set editing-mode emacs')
        if hasattr(readline, "read_history_file"):
            try:
                readline.read_history_file(HISTFILE)
            except IOError:
                pass
            atexit.register(readline.write_history_file, HISTFILE)
            
        blank = re.compile('^[ \t\n\r]*$')

        while True:
            try:
                s = raw_input('query > ')   # Use raw_input on Python 2
                if blank.match(s): continue
                run_query(opts, s)
            except (EOFError, StopIteration):
                break
