#! /usr/bin/env python

# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
# 
#   http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.    

import inspect
import os
import sys
import types
from tashi.services.ttypes import *
from thrift.protocol.TBinaryProtocol import TBinaryProtocol
from thrift.transport.TTransport import TBufferedTransport
from thrift.transport.TSocket import TSocket

from tashi.services import clustermanagerservice
from tashi import vmStates

from tashi.util import getConfig

def makeHTMLTable(list):
	(stdin_r, stdin_w) = os.pipe()

# XXXpipe: find number of columns in current window
	pipe = os.popen("tput cols")
	columns = pipe.read().strip()
	keys = {}
	for k in list:
		for k2 in k.__dict__.keys():
			if (not k2.endswith("Obj")):
				keys[k2] = k2
	if ('id' in keys):
		del keys['id']
		keylist = ['id'] + keys.keys()
	else:
		keylist = keys.keys()
	output = "<html>"
	output = output + "<table>"
	output = output + "<tr>"
	for k in keylist:
		output = output + "<td>%s</td>" % (k)
	output = output + "</tr>"
	for k in list:
		output = output + "<tr>"
		for k2 in keylist:
			if (k2 == "state"):
				output = output + "<td>%s</td>" % (str(vmStates[k.__dict__.get(k2, None)]))
			else:
				output = output + "<td>%s</td>" % (str(k.__dict__.get(k2, None)))
		output = output + "</tr>"
	output = output + "</table>"
	output = output + "</html>"
	pid = os.fork()
	if (pid == 0):
		os.close(stdin_w)
		os.dup2(stdin_r, 0)
		os.close(stdin_r)
		os.execl("/usr/bin/lynx", "/usr/bin/lynx", "-width=%s" % (columns), "-dump", "-stdin")
		sys.exit(-1)
	os.close(stdin_r)
	os.write(stdin_w, output)
	os.close(stdin_w)
	os.waitpid(pid, 0)

def getFunction(argv):
	"""Tries to determine the name of the function requested by the user -- may be called multiple times if the binary name is 'client'"""
	function = "None"
	if (len(argv) > 0):
		function = argv[0].strip()
		if (function.rfind("/") != -1):
			function = function[function.rfind("/")+1:]
		if (function.rfind(".") != -1):
			function = function[:function.rfind(".")]
	return function

def getFunctionInfo(m):
	"""Gets a string that describes a function from the interface"""
	f = getattr(clustermanagerservice.Iface, m)
	argspec = inspect.getargspec(f)[0][1:]
	return m + inspect.formatargspec(argspec)

def usage():
	"""Print program usage"""
	print "Available methods:"
	for m in methods:
		print "\t" + getFunctionInfo(m)
	print
	print "Examples:"
	print "\tgetInstances"
	print "\taddUser 'User(d={\"username\":\"foobar\"})'"
	print "\tremoveUser 2"
	print "\tcreateVM 1 1"

def simpleType(obj):
	"""Determines whether an object is a simple type -- used as a helper function to pprint"""
	if (type(obj) is not type([])):
		if (not getattr(obj, "__dict__", None)):
			return True
	return False

def pprint(obj, depth = 0, key = None):
	"""My own version of pprint that prints out a dict in a readable, but slightly more compact format"""
	valueManip = lambda x: x
	if (key):
		keyString = key + ": "
		if (key == "state"):
			valueManip = lambda x: vmStates[x]
	else:
		keyString = ""
	if (type(obj) is type([])):
		if (reduce(lambda x, y: x and simpleType(y), obj, True)):
			print (" " * (depth * INDENT)) + keyString + str(obj)
		else:
			print (" " * (depth * INDENT)) + keyString + "["
			for o in obj:
				pprint(o, depth + 1)
			print (" " * (depth * INDENT)) + "]"
	elif (getattr(obj, "__dict__", None)):
		if (reduce(lambda x, y: x and simpleType(y), obj.__dict__.itervalues(), True)):
			print (" " * (depth * INDENT)) + keyString + str(obj)
		else:
			print (" " * (depth * INDENT)) + keyString + "{"
			for (k, v) in obj.__dict__.iteritems():
				pprint(v, depth + 1, k)
			print (" " * (depth * INDENT)) + "}"
	else:
		print (" " * (depth * INDENT)) + keyString + str(valueManip(obj))

def main():
	"""Main function for the client program"""
	global INDENT, methods, exitCode
	exitCode = 0
	INDENT = (os.getenv("INDENT", 4))
	methods = filter(lambda x: not x.startswith("__"), clustermanagerservice.Iface.__dict__.keys())
	function = getFunction(sys.argv)
	if (function == "client"):
		function = getFunction(sys.argv[1:])
	if (function == "--makesyms"):
		for m in methods:
			os.symlink(sys.argv[0], m)
		sys.exit(0)
	if (function == "--rmsyms"):
		for m in methods:
			os.unlink(m)
		sys.exit(0)

	(config,configFiles) = getConfig(["Client"])
	cfgHost = config.get('Client', 'clusterManagerHost')
	cfgPort = config.get('Client', 'clusterManagerPort')
	cfgTimeout = float(config.get('Client', 'clusterManagerTimeout'))
	host = os.getenv('TASHI_CM_HOST', cfgHost)
	port = os.getenv('TASHI_CM_PORT', cfgPort)
	timeout = float(os.getenv('TASHI_CM_TIMEOUT', cfgTimeout)) * 1000.0

	socket = TSocket(host, int(port))
	socket.setTimeout(timeout)
	transport = TBufferedTransport(socket)
	protocol = TBinaryProtocol(transport)
	client = clustermanagerservice.Client(protocol)
	client._transport = transport
	client._transport.open()
	f = getattr(client, function, None)
	if not f:
		usage()
		sys.exit(-1)
	args = map(lambda x: eval(x), sys.argv[1:])
	try:
		res = f(*args)
		def cmp(x, y):
			try:
				if (x.id < y.id):
					return -1
				elif (y.id < x.id):
					return 1
				else:
					return 0
			except Exception, e:
				return 0
		if (type(res) == types.ListType):
			res.sort(cmp)
		if (os.getenv("USE_HTML_TABLES")):
			try:
				makeHTMLTable(res)
			except:
				pprint(res)
		else:
			pprint(res)
	except TashiException, e:
		print e.msg
		exitCode = e.errno
	except TypeError, e:
		print e
		print "\t" + getFunctionInfo(function)
		exitCode = -1
	finally:
		client._transport.close()
	sys.exit(exitCode)

if __name__ == "__main__":
	main()
