#!/usr/bin/env python
# -*- coding: utf-8 -*-
import vaex.ui.colormaps
import numpy as np
from optparse import OptionParser
import os
import sys
#import sampy

#import thread
#import threading
import time
import itertools
import platform


import vaex.dataset
import imp


#import matplotlib
import matplotlib.pyplot as plt


from flask import Flask, url_for, make_response, request, Response
app = Flask(__name__)
from flask.ext.compress import Compress
app.config['COMPRESS_MIMETYPES'] = ['application/octet-stream', 'text/html', 'text/css', 'text/xml', 'application/json', 'application/javascript']
c = Compress(app)

import flask


dataset_map = {}
dataset_list = []

def open(path, *args, **kwargs):
	try:
		print "opening", path
		dataset = vaex.open(path, *args, **kwargs)
		if dataset is not None:
			if dataset.name not in dataset_map:
				dataset_map[dataset.name] = dataset
				dataset_list.append(dataset)
		return dataset
	except Exception, e:
		print >>sys.stderr, "error opening", path, e

path_list = [os.path.expanduser('~/.vaex/webvaex.py'), "/etc/webvaex.py"]
key = "WEBVAEX_STARTUP"
if key in os.environ:
	path_list.append(key)

for path in sys.argv[1:]:
	open(path)
custom_module = None
for path in path_list:
	if os.path.exists(path):
		print "loading", path
		custom_module = imp.load_source('vaex.web.custom', path)
	else:
		print >>sys.stderr, path, "does not exist"
if custom_module:
	custom_module.open_datasets(sys.modules[__name__])


@app.route('/')
def api_root():
    return 'Welcome <a href="/list">list</a>'

import json
@app.route('/datasets')
def api_datasets():
	print "request for datasets"
	names = []
	for dataset in dataset_list:
		names.append(dataset.name)
	js = json.dumps(names)
	response= Response(js, status=200, mimetype='application/json')
	return response
	
	
@app.route('/colormaps')
def colormaps():
	js = json.dumps(vaex.ui.colormaps)
	response= Response(js, status=200, mimetype='application/json')
	return response


@app.route('/datasets/<dataset>/columns')
def api_columns(dataset):
	dataset = dataset_map[dataset]
	js = json.dumps(dataset.column_names)
	response= Response(js, status=200, mimetype='application/json')
	return response

@app.route('/datasets/<dataset>/info')
def api_info(dataset):
	dataset = dataset_map[dataset]
	js = json.dumps(dict(column_names=dataset.get_column_names(), length=dataset.full_length()))
	response= Response(js, status=200, mimetype='application/json')
	return response


import StringIO
import vaex.vaexfast

@app.route('/datasets/<name>/minmax/<x>')
@app.route('/datasets/<name>/minmax/<x>/<y>')
def api_range(name, x, y=None):
	dataset = dataset_map[name]
	expressions = [x]
	if y is not None:
		expressions.append(y)
	expr = dataset(*expressions)
	values = expr.minmax()
	data = {}
	for expression, (min, max) in zip(expressions, values):
		data[expression] = dict(min=min, max=max)
	#blockx = dataset.columns[x]
	#data = {"min":float(np.min(blockx)), "max":float(np.max(blockx))}
	#print data
	js = json.dumps(data)
	response= Response(js, status=200, mimetype='application/json')
	return response

@app.route('/datasets/<name>/minmax')
def api_minmax(name):
	return simple_handle(name, "minmax")


@app.route('/datasets/<name>/var')
def api_var(name):
	return simple_handle(name, "var")

@app.route('/datasets/<name>/mean')
def api_mean(name):
	return simple_handle(name, "mean")

@app.route('/datasets/<name>/sum')
def api_sum(name):
	return simple_handle(name, "sum")

@app.route('/datasets/<name>/limits_sigma')
def api_limits_sigma(name):
	return simple_handle(name, "limits_sigma")

@app.route('/datasets/<name>/select')
def api_select(name):
	dataset = dataset_map[name]
	expression = json.loads(request.args["expression"])
	result = dataset.select(expression)
	result = 0
	response= Response(json.dumps(result), status=200, mimetype='application/json')
	return response

import inspect
def simple_handle(name, method_name):
	dataset = dataset_map[name]
	expressions = json.loads(request.args["expressions"])
	expr = dataset(*expressions)
	if json.loads(request.args.get("masked", "false")):
		print "using masked"
		expr = expr.selected()
	method = getattr(expr, method_name)
	args, varargs, kwargs, defaults = inspect.getargspec(method)
	print inspect.getargspec(method)
	#args_required = args[:len(args)-len(defaults)]
	kwargs = {}
	for arg in args:
		if arg in request.args:
			kwargs[arg] = json.loads(request.args[arg])
	print "passing args", kwargs
	values = method(**kwargs)
	data = values.tolist()
	response= Response(json.dumps(data), status=200, mimetype='application/json')
	return response

@app.route('/datasets/<name>/histogram')
def api_histogram(name):
	dataset = dataset_map[name]
	print "histogram for", name, repr(request.args["expressions"])
	expressions = json.loads(request.args["expressions"])
	print "expressions=", expressions
	limits = json.loads(request.args["limits"])
	print "limits=", limits
	size = json.loads(request.args["size"])
	print "size=", size
	expr = dataset(*expressions)
	if json.loads(request.args.get("masked", "false")):
		expr = expr.selected()
	grid = expr.histogram(limits=limits, size=size)
	print "grid=", grid, grid.sum()
	f = StringIO.StringIO()
	response = make_response(grid.tostring())
	response.mimetype = 'application/octet-stream'
	return response


@app.route('/plot/<name>/<x>/<y>')
def api_density_xy(name, x, y=None):
	dpi=100.
	fig = plt.figure(dpi=dpi)
	fig.set_size_inches(512./dpi, 512./dpi)
	#plt.figure(figsize=(512/my_dpi, 800/my_dpi), dpi=my_dpi)
	#ax = fig.add_subplot(111)
	ax = plt.Axes(fig, [0., 0., 1., 1.])
	ax.set_axis_off()	
	fig.add_axes(ax)
	Ngrid = 512
	counts = np.zeros((Ngrid, Ngrid), dtype=np.float64)
	dataset = dataset_map[name]
	blockx = dataset.columns[x].astype(np.float64)
	blocky = dataset.columns[y].astype(np.float64)
	sub_i1, sub_i2 = 0, dataset._length
	ranges = [0, 100, 0, 100]
	if "ranges" in request.args:
		ranges = map(float, request.args["ranges"].split(","))
	colormap = request.args.get("colormap", "jet")
	sub_counts = [counts]
	print ranges
	index = 0
	print blockx[sub_i1:sub_i2].shape, blocky[sub_i1:sub_i2].shape, None, sub_counts[index].shape, ranges
	vaexfast.histogram2d(blockx[sub_i1:sub_i2], blocky[sub_i1:sub_i2], None, sub_counts[index], *ranges)
	print "next"
	ax.imshow(np.log10(counts), origin="lower", extent=ranges, cmap=colormap)
	ax.set_aspect('auto')
	#ax.set_axis_off()
	f = StringIO.StringIO()
	fig.savefig(f)
	data = f.getvalue()
	print len(data)

	response = make_response(f.getvalue())
	response.mimetype = 'image/png'
	return response
	
	#return 'Plot ' +name  +":" + x+ " / " +y
    
    
    


if __name__ == '__main__':
	#flask.url_for('static', filename='test.html')
	app.run(host='0.0.0.0')
	#api_density_xy("Aq-A-2-999-shuffled-1percent", "x", "y")