#!/usr/bin/env python

import getopt, sys, urllib, urllib2, re, pwd, os, HTMLParser
from os.path import *

CACHE_DIR = expanduser("~/.horairefsa")

POSTDATA = "code=%(code)s&V2=%(quadri)s&query=%(query)s"
URL = "http://perception.fsa.ucl.ac.be/h_affcod.asp"

PAS_DONNE = re.compile('.*Ce cours.*pas.*')

JOURS = ["Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"]
HEURES = ["08h30-10h30", "10h45-12h45", "14h00-16h00", "16h15-18h15"]

def pretty_print(grille):
	if grille == None:
		return "Aucun Cours"
		
	string = ""
	for j in range(len(grille[0])):
		string = string + JOURS[j] + ":\n"
		for i in range(len(grille)):
			for cours in grille[i][j]:
				string = string + "\t"
				if len(grille[i][j]) > 1:
					# Conflit horaire
					string = string + HEURES[i] + "***"
				else:
					string = string + HEURES[i]
				string = string + "\t" + cours + "\n"
	
	return string[:-1]
	
def merge_horaires(grille, horaire):
	if grille == None:
		return horaire
		
	for i in range(len(horaire)):
		for j in range(len(horaire[i])):
			if horaire[i][j] == None:
				continue
			
			for cours in horaire[i][j]:
				grille[i][j].append(cours)
	
	return grille
	
class CoursHtmlParser(HTMLParser.HTMLParser):
	def __init__(self):
		HTMLParser.HTMLParser.__init__(self)
	
	def get_table(self, page):
		self.chars = ""
		self.table_horaire = []
		
		self.feed(page)
		self.close()
		
		return self.table_horaire[1:-1]
		
	def handle_starttag(self, tag, attrs):
		tag = tag.lower()
		if tag == "tr":
			# Start a new row
			self.table_horaire.append([])
		elif tag == "td":
			# Start a new cell
			self.chars = ""

	def handle_endtag(self, tag):
		tag = tag.lower()
		if tag == "td" and not self.chars in ("12", "34", "56", "78"):
			# Start a new cell
			if self.chars == "":
				self.table_horaire[-1].append([])
			else:		
				self.table_horaire[-1].append([self.chars])

	def handle_data(self, chars):
		self.chars = self.chars + chars

cours_parser = CoursHtmlParser()
def parse_horaire(horaire):
	horaire = ' '.join(horaire.split('\n'))
	if PAS_DONNE.match(horaire):
		return (False, "")
	else:
		table = cours_parser.get_table(horaire)
		return (True, table)
		
def download_cours(cours, quadri=1):
	# If we have a cache, use it
	cache_file = join(CACHE_DIR, "%s-Q%d.html" % (cours, quadri))
	if exists(cache_file):
		return file(cache_file).read()
		
	payload = POSTDATA % {
		"code" : cours,
		"quadri" : quadri,
		"query": urllib.quote_plus("Afficher l'horaire du cours choisi")
		}
	req = urllib2.Request(URL, payload, {
		"Referer": "http://perception.fsa.ucl.ac.be/h_codes.asp",
		"Content-Type": "application/x-www-form-urlencoded"
		})
	#Download the page
	sys.stderr.write("Downloading %s...\n" % cache_file)
	page = urllib2.urlopen(req).read()
	# Cache it
	file(cache_file, 'w').write(page)
	
	return page

def got_error(err):
	sys.stderr.write("%s\n" % err)
			
def usage():
	print """=== Horaires FSA: Aide
$ horairefsa [OPTIONS] COURS [COURS...]

Donne l'horaire du/des cours donne sous la forme du sigle.
	Exemples
		$ horairefsa ELEC2525
		$ horairefsa ingi2141 ingi2142

OPTIONS:
	-h, --help			Affiche cette aide.
	-c, --clear			Efface tous les fichiers caches.
"""
	sys.exit()
	
if __name__ == "__main__":
	if not exists(CACHE_DIR):
		os.mkdir(CACHE_DIR)
		
	try:
		opts, args = getopt.getopt(sys.argv[1:], "hc", ["help", "clear"])
	except getopt.GetoptError:
		usage()
	
	for o, a in opts:
		if o in ("-h", "--help"):
			usage()
		elif o in ("-c", "--clear"):
			files = os.listdir(CACHE_DIR)
			for f in files:
				os.unlink(join(CACHE_DIR, f))
				
			print 'Les fichiers suivants ont ete effaces de %s: %r' % (CACHE_DIR, files)
			sys.exit()
			
	#Parameter validation
	if len(args) == 0:
		print 'Vous devez specifier au moins un code de cours !'
		usage()
		
	# Remove duplicate courses and uppercase
	liste_cours = []
	for cours in args:
		if not cours.upper() in liste_cours:
			liste_cours.append(cours.upper())
		
	horaire = []	
	for cours in liste_cours:
		try:
			horaire.append( (cours, download_cours(cours), download_cours(cours, 2)) )
		except Exception, msg:
			got_error(msg)

	grille_q1 = None
	grille_q2 = None
	for cours in horaire:
		cours, q1, q2 = cours
		actif_q1, quand_q1 = parse_horaire(q1)
		actif_q2, quand_q2 = parse_horaire(q2)
		
		if actif_q1:
			grille_q1 = merge_horaires(grille_q1, quand_q1)	
				
		if actif_q2:
			grille_q2 = merge_horaires(grille_q2, quand_q2)
		
		if not actif_q1 and not actif_q2:
			got_error('** Le cours %s est introuvable (seminaire ou pas dans l\'horaire FSA, .. ) ?!' % cours)
	
	print '1er Quadri:'
	print pretty_print(grille_q1)
	print '---------------------------------------------------------------------'
	print '2eme Quadri:'
	print pretty_print(grille_q2)
