#!/usr/bin/python

import sys, os, re, pexpect, time, Cookie
import Log, common

try:
	from Config import libPaths, dbName, dbUser, dbPass, dbHost, dbPort
except:
	Log.Message ("Error occured in finding basic configuration paramaters. Reverting to installer.", "index.py", "ERROR")
	import install
	sys.exit ()

for path in libPaths: sys.path.append (path)

try:
	import pycisco, pyaaa
except:
	Log.Message ("Couldn't import pycisco or pyaaa. Reverting to installer.", "index.py", "ERROR")
	import install
	sys.exit ()

import cgi, cgitb
cgitb.enable ()

form = cgi.FieldStorage ()

defaultCursor = None
def GetDefaultCursor ():
	global defaultCursor
	if defaultCursor == None:
		defaultCursor = pyaaa.SafeBase ()
		defaultCursor._Resume (sessionID)
	return defaultCursor

# Cookie stuff
sessionID = None
def ProcessCookie ():
	global sessionID
	cookie = Cookie.SimpleCookie (os.environ.get("HTTP_COOKIE", ""))
	if cookie.has_key ("sid"):
		sessionID = cookie["sid"].value 
		try:
			GetDefaultCursor ()
		except pyaaa.InvalidSession:
			# TODO: Remember when this happens to catch people trying to brute-force session IDs.
			Log.Message ("Invalid session ID: " + sessionID + ". Redirecting to login.", "index.py", "ERROR")
			print "Location: login.py"
	else:
		# Not logged in, fail.
		Log.Message ("User not logged in. Redirecting to login.", "index.py", "ERROR")
		print "Location: login.py"


def GetSwitchList ():
	global switchList
	if switchList == []:
		switchList = GetDefaultCursor ()._GetRecords ("NetworkDevice")
	return switchList

def ShowDefaultPage ():
	pageText = """
		<p>Select a switch to get started!</p>
		<form action='index.py' method='get'>
		<select name='switch'>
	"""

	for switch in GetSwitchList ():
		pageText += "<option value='" + switch.split(".")[0] + "'>" + switch.split(".")[0] + "</option>"
	
	pageText += """
		</select>
		<input type='hidden' name='action' value='status' />
		<input type='submit' value='View Port Summary' />
		</form>
	"""

	return pageText

def ShowSwitchStatus (switchName):
	pageText = """
	<h3>Port summary for %(switchName)s</h3>
	<script type='text/javascript'>
	$(document).ready (function () {
		$("a.portfast").click (function () {
			// Change the appearance and class so that it's no longer a "reveal"-style link
			$(this).attr ("class", "portfastload");
			$(this).text ("Wait...");
			
			portName = $(this).parents("tr").attr ('id');
			$(this).load ("update.py?action=getportfast&switch=%(switchName)s&port=" + portName);
			$(this).unbind ();
			$(this).click (togglePortfast);
		});
		$("a.errors").click (function () {
			$(this).attr ("class", "errorsload");
			$(this).text ("Wait...");
			td = $(this).parents ("td");
			portName = $(this).parents("tr").attr ('id');
			td.load ("update.py?action=geterrors&switch=%(switchName)s&port=" + portName);
		});
		$("a.status").click (function () {
			$(this).attr ("class", "statusload");
			$(this).text ("Wait...");
			td = $(this).parents ("td");
			portName = $(this).parents("tr").attr ('id');
			$(this).load ("update.py?action=toggleshutdown&switch=%(switchName)s&port=" + portName);
		});
		togglePortfast = function () {
			$(this).text ("Wait...");
			portName = $(this).parents("tr").attr ('id');
			$(this).load ("update.py?action=toggleportfast&switch=%(switchName)s&port=" + portName);
		};
		toggleShutdown = function () {
			$(this).text ("Wait...");
			portName = $(this).parents("tr").attr ('id');
			$(this).load ("update.py?action=toggleshutdown&switch=%(switchName)s&port=" + portName);
		};
		descClick = function () {
			$(this).attr ("class", "descinput");
			portName = $(this).parents("tr").attr ('id');
			td = $(this).parents ("td");
			td.html ("<input type='text' value='" + $(this).text() + "' />");
			td.children ().focus ().blur (function () {
				portName = $(this).parents("tr").attr ('id');
				portDesc = $(this).attr ("value");
				td = $(this).parents ("td");
				td.html ("<a style='cursor:pointer'>Saving...</a>");
				td.children ().click (descClick);
				td.children().load ("update.py?action=setdescription&switch=%(switchName)s&port=" + portName + "&desc=" + escape (portDesc));
			});
			//td.load ("update.py?action=geterrors&switch=%(switchName)s&port=" + portName);
		};
		vlanClick = function () {
			$(this).attr ("class", "vlaninput");
			portName = $(this).parents("tr").attr ('id');
			td = $(this).parents ("td");
			td.html ("<input type='text' value='" + $(this).text() + "' />");
			td.children ().focus ().blur (function () {
				portName = $(this).parents("tr").attr ('id');
				vlan = $(this).attr ("value");
				td = $(this).parents ("td");
				td.html ("<a style='cursor:pointer'>Saving...</a>");
				td.children ().click (vlanClick);
				td.children().load ("update.py?action=setvlan&switch=%(switchName)s&port=" + escape(portName) + "&vlan=" + escape (vlan));
			});
		};
		$("a.desc").click (descClick);
		$("a.vlan").click (vlanClick);
	});
	</script>
	""" % {'switchName' : switchName}
	
	try:
		switch = pyaaa.SafeObject (pycisco.NetworkDevice (), switchName)
		switch._Resume (sessionID)
		switch._Remap ("Connect", {"hostname" : "hostname", "username" : "usern", "password" : "passw", "enable" : "enablepw"})
		switch.Connect ()
		ports = switch.GetPortSummary ()
	except pexpect.TIMEOUT:
		pageText += "<h3 style='color:rgb(255,0,0)'>Switch appears to be down.</h3>"
		return pageText


	pageText += """
	<table border='0' cellpadding='2' cellspacing='0' class='rowset' >
	<tr>
	<th>Number</th>
	<th>Description</th>
	<th>Connected</th>
	<th>VLAN</th>
	<th>Duplex</th>
	<th>Speed</th>
	<th>Media</th>
	<th>Portfast</th>
	<th>Errors</th>
	</tr>
	"""
	even = True
	for port in ports:
		pageText += """
		<tr class='%s' id='%s'>
		<td>%s</td>
		<td><a style='cursor:pointer' class='desc'>%s</a></td>
		<td><a style='cursor:pointer' class='status'>%s</a></td>
		<td><a style='cursor:pointer' class='vlan'>%s</a></td>
		<td>%s</td><td>%s</td><td>%s</td>
		<td><a style='cursor:pointer' class='portfast'>%s</a></td>
		<td><a style='cursor:pointer' class='errors'>%s</td>
		</tr>
		""" % (even and "even" or "odd", port["name"], port["name"], port["description"] or "(not set)", port["connectstate"], port["vlan"], port["duplex"], port["speed"], port["media"], port["portfast"], port["errors"])
		even = not even
	pageText += "</table>"

	return pageText


def GetBody ():
	if not form.has_key ("action"):
		pageText = ShowDefaultPage ()
	elif form["action"].value == "status":
		if not form.has_key ("switch"):
			pageText = "Missing switch argument, please stop trying to craft your own URLs!"
		else:
			pageText = ShowSwitchStatus (form["switch"].value)

	return pageText

def GetSidebar ():
	pageText = """
	<dt><a href="./">Navigation</a></dt>
	<dd><ul>
	<li><a href="./">Main Menu</a></li>
	"""
	if defaultCursor._admin == True: pageText += "<li><a href='./configure.py'>Configuration</a></li>"
	pageText += """
	<li><a href="logout.py">Log Out</a></li>
	</ul></dd>
	<dt><a href="./">Switches</a></dt>
	<dd><ul>
	"""
	for switch in GetSwitchList ():
		pageText += '<li><a href="./?action=status&switch=' + switch.split(".")[0] + '">' + switch.split(".")[0] + '</a></li>'
	pageText += '</ul></dd>'
	return pageText

switchList = []
pageBuffer = ""
pageBuffer += "Content-Type: text/html\n\n"
try:
	ProcessCookie ()
	pageBuffer += common.GetHeader ("Port Administration Configuration Tool", GetSidebar ())
	pageBuffer += GetBody ()
except pyaaa.DatabaseError:
	pageBuffer += common.GetHeader ("Error - Port Administration Configuration Tool", common.GetErrorSidebar ())
	pageBuffer += "There was a problem with the database. Please contact your system administrator."
except pyaaa.SessionExpired:
	print "Location: login.py"
	print
pageBuffer += common.GetFooter ()

print pageBuffer
