import sys, os, fnmatch, shutil
from datetime import datetime
from token import Token

"""
Template for index page
"""

indexHeader = """<!doctype html>
<html>
<head>
	<meta charset="utf-8">
	<title>Java Cross-Indexer</title>
	<link rel="stylesheet" href="static/style.css" type="text/css">
</head>
<body>
	<h1>Java Cross-Indexer</h1>
		<dt>Last run</dt>
		<dd><time>%s</time></dd>
		<dt>in directory</dt>
		<dd><kbd>%s</kbd></dd>
	<ul>
"""

indexFooter = """	</ul>
</body>
</html>
"""

indexLinkLine = '\t\t<li><a href="%s">%s</a></li>\n'
indexLinkLineMain = '\t\t<li><a href="%s">%s</a> <a href="%s#main(java.lang.String[])">main</a></li>\n'

"""
Template for class page
"""

classHeader = """<!doctype html>
<html>
<head>
	<meta charset="utf-8">
	<title>%s</title>
	<link rel="stylesheet" href="%sstatic/style.css" type="text/css">
	<script src="%sstatic/highlight.js"></script>
</head>
<body>
	<h1>%s</h1>
	<ol class="javaclass">"""

classFooter = """	</ol>
</body>
</html>
"""


"""
Ensure that directorys exists to contain a file.
"""
def ensureDir(f):
	d = os.path.dirname(f)
	if not os.path.exists(d):
		os.makedirs(d)

"""
Get a URL to a class page, relative to another page
"""
def getClassURL(className, page):
	classPage = className.replace('.', os.path.sep) + '.html'
	if 'java' in className:
		return 'http://docs.oracle.com/javase/7/docs/api/' + classPage
	else:
		return os.path.relpath(classPage, page)

"""
Render a token on a page as text/html
"""
def tokenToHTML(tok, page):
	text = tok.text.replace('\t', '    ')\
		.replace('&', '&amp;')\
		.replace('<', '&lt;')\
		.replace('>', '&gt;')\
		.replace('"', '&quot;')\
		.replace('\'', '&apos;')
	tokType = tok.get_type()
	if tok.tok_type == Token.METHOD_INVOCATION:
		# make a link to the declaration of the method
		s = tok.class_name.split('$', 2)
		if len(s) == 2:
			(outerclass, innerclass) = s
			rel_file = getClassURL(outerclass, page)
			link = rel_file + '#' + innerclass + '$' + tok.text + tok.method_type
		else:
			rel_file = getClassURL(tok.class_name, page)
			link = rel_file + '#' + tok.text + tok.method_type
		return '<a href="' + link + '" class="' + tokType + '">' + text + '</a>'
	elif tok.tok_type == Token.METHOD_DECLARATION:
		# make an anchor for the declaration, that can be linked to
		name = tok.text + tok.method_type
		sp = tok.class_name.split('$',2)
		if len(sp) > 1:
			name = sp[1]+'$'+name
		return '<a id="' + name + '" class="' + tokType + '">' + text + '</a>'
	elif tokType:
		# render a token of a given type
		return '<span class="' + tokType + '">' + text + '</span>'
	else:
		# render an unstyled token
		return text

"""
Renderer
Converts data about Java classes into HTML pages
"""
class Renderer(object):
	def __init__(self, outputDir, inputDir):
		self.path = outputDir
		self.inputPath = os.path.abspath(inputDir)
		scriptDir = os.path.dirname(sys.argv[0])
		self.staticSource = os.path.join(scriptDir, 'static')
		self.staticDest = os.path.join(self.path, 'static')

	"""
	Copy static files into XREF directory
	"""
	def copyStatics(self):
		print "Copying static files"
		for srcDir, dirs, files in os.walk(self.staticSource):
			dstDir = srcDir.replace(self.staticSource, self.staticDest)
			if not os.path.exists(dstDir):
				os.mkdir(dstDir)
			for file in files:
				srcFile = os.path.join(srcDir, file)
				shutil.copy(srcFile, dstDir)

	"""
	Create and write an HTML page for a Java class
	"""
	def renderClass(self, classData):
		# get the primary classname
		className = classData['class_name']
		print "Rendering " + className
		dirs = className.split('.')
		path = os.path.dirname(os.path.join(*dirs))
		page1 = os.path.join(*dirs)+'.html'
		page = os.path.join(self.path, *dirs)+'.html'
		ensureDir(page)
		rootDir = "../" * (len(dirs)-1)
		self.renderIndexLine(page1, className, classData['has_main'])
		with open(page, 'w') as f:
			f.write(classHeader % (className, rootDir, rootDir, className))
			for line in classData['lines']:
				f.write('<li>' +
						''.join([tokenToHTML(token, path) for token in line]) +
						'</li>\n')
			f.write(classFooter)

	"""
	Start writing an index page, with table of contents for classes.
	"""
	def renderIndexHeader(self):
		print "Rendering index"
		page = os.path.join(self.path, 'index.html')
		ensureDir(page)
		self.index = open(page, 'w')
		timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
		self.index.write(indexHeader % (timestamp, self.inputPath))

	"""
	Write a line of table of contents for one class
	"""
	def renderIndexLine(self, fileName, className, hasMain):
		if hasMain:
			line = indexLinkLineMain % (fileName, className, fileName)
		else:
			line = indexLinkLine % (fileName, className)
		self.index.write(line)
		self.index.flush()

	"""
	Finish up writing the index page
	"""
	def renderIndexFooter(self):
		self.index.write(indexFooter)
		self.index.close()
