GETMET = 0
POSTMET = 1
GETONLY = DEFAULT = [GETMET]
POSTONLY = [POSTMET]
ALLMETS = GETONLY + POSTONLY
PAGES = tuple()

class Para:
	def __init__(self, innerHTML, props=None):
		self.innerHTML = innerHTML
		self.props = props
		if not isinstance(self.props, dict):
			self.props = {}
		elif type(self.props) != dict:
			self.props = dict(self.props)
		self.html = "p"

	def __str__(self):
		def escapeHTML(txt):
			res = ""
			for char in txt:
				res += "&#" + str(ord(char)) + ";"
			return res
		return "<" + self.html + ">" + escapeHTML(self.innerHTML) + "</" + self.html + ">"

class Header(Para):
	def __init__(self, innerHTML, props=None):
		self.innerHTML = innerHTML
		self.props = props
		if not isinstance(self.props, dict):
			self.props = {}
		elif type(self.props) != dict:
			self.props = dict(self.props)
		self.html = "h" + str(self.props["size"])

def page(route, opts=None):
	if opts is None:
		opts = {}
	opts = dict(opts)
	if "met" not in opts:
		opts["met"] = ALLMETS
	def decor(func):
		if not route.startswith("/"):
			raise ValueError(repr(route) + " should begin with " + repr("/"))
		PAGES = list(globals()["PAGES"])
		PAGES.append((route, func, opts))
		globals()["PAGES"] = tuple(PAGES)
		del locals()["PAGES"]
		def wrap(*args, **kwargs):
			res = func(*args, **kwargs)
			if not isinstance(res, tuple):
				raise ValueError(str(func).split(" ")[1] + " did not return a tuple")
			for elem in res:
				if not isinstance(elem, Para):
					raise ValueError("One of " + str(func).split(" ")[1] + "'s elements was not a valid " + __name__)
			return res
		return wrap
	return decor

def addFile(file):
	PAGES = list(globals()["PAGES"])
	def returnResp():
		import flask
		return flask.send_from_directory(".", file)
	PAGES.append(("/" + file, returnResp, {"met": GETONLY}))
	globals()["PAGES"] = tuple(PAGES)
	del locals()["PAGES"]

def start(host, port):
	import flask, threading
	app = flask.Flask(__name__) # The module name will fit :)
	@app.route("/<path:path>", methods=["GET", "POST"])
	@app.route("/", methods=["GET", "POST"])
	def endpnt(path=None):
		if path is None:
			path = ""
		path = "/" + path
		foundEndpnt = False
		count = 0
		while count != len(globals()["PAGES"]):
			endpnt = globals()["PAGES"][count]
			if endpnt[0] == path:
				foundEndpnt = True
				break
			count += 1
		if not foundEndpnt:
			return flask.abort(404) # Page not found!!1
		endpntMets = endpnt[2]["met"]
		count = 0
		for met in endpntMets:
			endpntMets[count] = "GET" if met == GETMET else ("POST" if met == POSTMET else None)
			count += 1
		if flask.request.method.upper() not in endpntMets:
			return flask.abort(405)
		bdRes = endpnt[1]()
		def escapeHTML(txt):
			res = ""
			for char in txt:
				res += "&#" + str(ord(char)) + ";"
			return res
		count = 0
		if isinstance(bdRes, flask.Response):
			return bdRes
		bdRes = list(bdRes)
		for elem in bdRes:
			if isinstance(elem, str):
				elem = escapeHTML(elem)
			elem = str(elem)
			bdRes[count] = elem
			count += 1
		htmlRes = "<!-- Page generated by Buildington -->\n<!DOCTYPE html>\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<meta name=\"viewport\" content=\"width=device-width\">\n\t\t<title>Buildington</title>\n\t</head>\n\t<body>\n\t"
		for line in bdRes:
			htmlRes += "\t" + line + "\n\t"
		htmlRes += "</body>\n</html>"
		htmlRes = htmlRes.replace("<body>\n\t</body>", "<body></body>")
		return htmlRes
	app.run(host, port)