#!/usr/bin/python

import cgi
import shelve
import string

from ProcessLines import ProcessLines

def printHeader():
  print "content-type: text/html"
  print

#PAPER_DBM = "/home/ai/teevan/public_html/dbms/paper_dbm"
#PAPER_DBM = "/com/web/docs/people/teevan/dbms/paper_dbm"
PAPER_DBM = "/afs/csail.mit.edu/u/t/teevan/public_html/haystack/reading/paper_dbm"

BASE = "Main.cgi"
PAGEKEY = "page"
PASTPAGEKEY = "pastname"
ACTIONKEY = "action"
VIEWKEY = "View"
EDITKEY = "Edit"
ADDKEY = "add"

SCHEDULEKEY = "schedule"
PASTKEY = "past"
FUTUREKEY = "future"
PAPERSKEY = "papers"
IDKEY = "idcounter"

TITLEKEY = "TITLE"
URLKEY = "URL"
AUTHORSKEY = "AUTHORS"
PUBKEY = "PUB"
INFOKEY = "INFO"
TOPICKEY = "TOPIC"
TOPICFILTERKEY = "FILTER"
DATEKEY = "DATE"
READDATEKEY = "READ_DATE"
IDKEY = "ID"
NOTESKEY = "NOTES"
PASSWORDKEY = "PASSWORD"
ARCHIVENAMEKEY = "ARCHIVENAME"

class PaperOrganizer:

  # For now, when init'ing, artificially creat the lists.
  def __init__( self ):

    self.paperDict = {}

    self.papers = []
    self.past = []
    self.future = []
    self.schedule = []

    try:
      self.paperDict = shelve.open( PAPER_DBM )
      #self.printStored()
    except:
      print "Trouble opening database: " + PAPER_DBM

  def printStored( self ):
    print "<h1>Stored:</h1>"
    for key in self.paperDict.keys():
      print key + ": " + repr( self.paperDict[ key ] ) + "<BR>"

  def record( self, key, value ):
    self.paperDict[ key ] = value

  def paperList( self ):
    if not self.papers and self.paperDict.has_key( PAPERSKEY ):
      self.papers = self.paperDict[ PAPERSKEY ]
    return self.papers

  def scheduleList( self ):
    if not self.schedule and self.paperDict.has_key( SCHEDULEKEY ):
      self.schedule = self.paperDict[ SCHEDULEKEY ]
    return self.schedule

  def futureList( self ):
    if not self.future and self.paperDict.has_key( FUTUREKEY ):
      self.future = self.paperDict[ FUTUREKEY ]
    return self.future

  def pastList( self ):
    if not self.past and self.paperDict.has_key( PASTKEY ):
      self.past = self.paperDict[ PASTKEY ]
    return self.past

  # Get a dict of the papers that are scheduled that is appropriate for
  # printing (PAPERS: list of paper names, <paper name>: dict of paper)
  def scheduleDict( self ):
    return self.getPaperDictFromIdList( self.scheduleList() )

  # Get a dict of the papers that are for future reading:
  def futureDict( self ):
    return self.getPaperDictFromIdList( self.futureList() )

  # Get a dict of tuples for the papers that have been read:
  # (PASTLIST: list of past dicts, <past dicts>: dict of papers,
  # including the title of the dict (PASTTITLE).
  def pastDict( self, desiredName ):
    retDict = {}
    pastList = []
    for listName, list in self.pastList():
      if listName == desiredName:
        retDict.update( self.getPaperDictFromIdList( list ) )
      pastList.append( listName )
    retDict[ "PASTLIST" ] = pastList
    retDict[ "PASTNAME" ] = desiredName
    return retDict

  def getPaperDictFromIdList( self, list ):
    retDict = {}
    paperList = []
    for pid in list:
      name = "paper" + repr( pid )
      paperList.append( name )
      retDict[ name ] = self.getPaper( pid )
    retDict[ "PAPERS" ] = paperList
    return retDict

  def getPaper( self, pid ):
    if pid >= len( self.paperList() ): return {}
    else: return self.paperList()[ pid ]

  def addPaper( self, form ):
    paper = self.createPaper( form )
    return self.storePaper( paper )

  def createPaper( self, form ):
    paper = {}
    self.addKeyToPaper( TOPICKEY, paper, form )
    self.addKeyToPaper( TITLEKEY, paper, form )
    self.addKeyToPaper( URLKEY, paper, form )
    self.addKeyToPaper( AUTHORSKEY, paper, form )
    self.addKeyToPaper( PUBKEY, paper, form )
    self.addKeyToPaper( INFOKEY, paper, form )
    self.addKeyToPaper( DATEKEY, paper, form )
    self.addKeyToPaper( READDATEKEY, paper, form )
    self.addKeyToPaper( IDKEY, paper, form )
    self.addKeyToPaper( NOTESKEY, paper, form )

    if paper.has_key( READDATEKEY ) and paper[ READDATEKEY ] == "Unknown":
      del( paper[ READDATEKEY ] )

    return paper

  def storePaper( self, paper ):
    where = SCHEDULEKEY

    # Now that the paper has been created, add it to the paper list:
    # If the paper already has an id, then it was already created before.
    # Get the old version of the paper.
    oldPaper = {}
    papers = self.paperList()
    if paper.has_key( IDKEY ):
      id = string.atoi( paper[ IDKEY ] )
      oldPaper = self.getPaper( id )
      papers[ id ] = paper
    else:
      id = len( papers )
      paper[ IDKEY ] = repr( id )
      papers.append( paper )

    self.papers = papers
    self.record( PAPERSKEY, papers )

    # If the paper is in the past list, it shouldn't be moved.
    inPastList = 0
    for name, idList in self.pastList():
      if id in idList: 
        inPastList = 1
        where = PASTKEY
        break

    # Add the paper to the appropriate place, removing it if necessary.
    # If the paper has a read date key, and the date has changed
    # from the old paper, then it needs to be stored in the schedule list
    # and the schedule list needs to be recoreded.  If the old paper didn't
    # have a date, it needs to be removed from the future list.
    if not inPastList:
      if paper.has_key( READDATEKEY ): 
        if not oldPaper.has_key( READDATEKEY ) and oldPaper.has_key( IDKEY ):
          list = self.removePaperFromList( oldPaper, self.futureList() )
          self.record( FUTUREKEY, list )
        list = self.scheduleList()
        if id not in list:
          list.append( id )
          list = self.sortList( list )
          self.schedule = list
          self.record( SCHEDULEKEY, list )
        where = SCHEDULEKEY
      else:
        if oldPaper.has_key( READDATEKEY ):
          list = self.removePaperFromList( oldPaper, self.scheduleList() )
          self.record( SCHEDULEKEY, list ) 
        list = self.futureList()
        if id not in list:
          list.append( id )
          list = self.sortList( list )
          self.future = list
          self.record( FUTUREKEY, list )
        where = FUTUREKEY

    return where

  def removePaperFromList( self, paper, list ):
    id = string.atoi( paper[ IDKEY ] )
    while id in list:
      i = list.index( id )
      list = list[ :i ] + list[ i+1: ]
    return list

  def sortList( self, list ):
    return list

  def addKeyToPaper( self, key, paper, form ):
    if form.has_key( key ):
      paper[ key ] = form[ key ].value    

  def archive( self, name ): 
    # Name can't have any spaces (I know, this sucks, fix later?)
    pieces = string.split( name )
    name = ""
    for piece in pieces:
      name = name + piece

    # Make the tuple to add to past:
    pastInfo = ( name, self.scheduleList() )
    past = self.pastList()
    past.append( pastInfo )
    self.schedule = []
    self.record( SCHEDULEKEY, [] )
    self.record( PASTKEY, past )

# Give the first date of the reading group
def make_read_dates( month, day ):

  months = [ ( "December", 31 ),
	     ( "January", 31 ),
             ( "February", 28 ),
	     ( "March", 31 ),
	     ( "April", 30 ),
	     ( "May", 31 ), 
	     ( "June", 30 ),
	     ( "July", 31 ),
	     ( "August", 31 ),
	     ( "September", 30 ),
	     ( "October", 31 ),
	     ( "November", 30 ) ]

  month = month%12

  dates = [ "Unknown" ]
  month_str, month_max_day = months[ month ]

  while( len( dates ) < 15 ):
    date_str = month_str + " " + repr( day )
    dates.append( date_str )
    day = day + 7
    if( day > month_max_day ):
      day = day - month_max_day
      month = (month + 1)%12
      month_str, month_max_day = months[ month ]

  return dates
  

if __name__ == '__main__':

  printHeader()

  form = cgi.FieldStorage()
  po = PaperOrganizer()

  page = SCHEDULEKEY
  #page = "1"
  if form.has_key( PAGEKEY ):
    page = form[ PAGEKEY ].value

  if form.has_key( PASSWORDKEY ):
    if form[ PASSWORDKEY ].value == "haymaster":
      if form.has_key( "Submit" ):
        page = po.addPaper( form )
      elif form.has_key( "Archive" ):
        po.archive( form[ ARCHIVENAMEKEY ].value )
        page = SCHEDULEKEY

  if page == SCHEDULEKEY: dict = po.scheduleDict()
  elif page == FUTUREKEY: dict = po.futureDict()
  elif page == PASTKEY: 
    pastpage = "Miscellaneous"
    if form.has_key( PASTPAGEKEY ): pastpage = form[ PASTPAGEKEY ].value 
    dict = po.pastDict( pastpage )
  else:
    # Page might be a paper to display individually:
    paperIdList = []
    try:
      paperIdList.append( string.atoi( page ) )
    except: 1 #Do nothing.
    dict = po.getPaperDictFromIdList( paperIdList )
    dict[ ACTIONKEY ] = "Edit"
    if form.has_key( ACTIONKEY ): dict[ ACTIONKEY ] = form[ ACTIONKEY ].value

  dict[ "BASE" ] = BASE
  dict[ "PAGEKEY" ] = PAGEKEY
  dict[ "PASTPAGEKEY" ] = PASTPAGEKEY
  dict[ "ACTIONKEY" ] = ACTIONKEY
  dict[ "VIEWKEY" ] = VIEWKEY
  dict[ "EDITKEY" ] = EDITKEY
  dict[ "ADDKEY" ] = ADDKEY

  dict[ "PAGE" ] = page
  dict[ "MENU" ] = [ SCHEDULEKEY, PASTKEY, FUTUREKEY, ADDKEY ]
  dict[ "SCHEDULE" ] = SCHEDULEKEY
  dict[ "FUTURE" ] = FUTUREKEY
  dict[ "PAST" ] = PASTKEY

  dict[ "PAGETITLE" ] = "Haystack Reading Group"
  dict[ "EMAIL" ] = "haystack-read@theory.lcs.mit.edu"
  dict[ "TIME" ] = "Fridays, 1:00 PM"
  dict[ "ROOM" ] = "NE43-204"

  dict[ "READDATES" ] = make_read_dates( 7, 4 )
  
  dict[ "TITLEKEY" ] = TITLEKEY
  dict[ "URLKEY" ] = URLKEY
  dict[ "AUTHORSKEY" ] = AUTHORSKEY
  dict[ "PUBKEY" ] = PUBKEY
  dict[ "INFOKEY" ] = INFOKEY
  dict[ "TOPICKEY" ] = TOPICKEY
  dict[ "DATEKEY" ] = DATEKEY
  dict[ "IDKEY" ] = IDKEY
  dict[ "READDATEKEY" ] = READDATEKEY
  dict[ "NOTESKEY" ] = NOTESKEY
  dict[ "ARCHIVENAMEKEY" ] = ARCHIVENAMEKEY
  dict[ "PASSWORDKEY" ] = PASSWORDKEY

  dict[ "TOPICS" ] = [ "Information Management", "Information Sharing", "Information Retrieval", "Personalization", "Machine Learning", "Databases", "User Interfaces", "Other" ]

  dict[ "LINKCOLOR" ] = "#FF0000"
  dict[ "ALINKCOLOR" ] = "#FF3232"
  dict[ "VLINKCOLOR" ] = "#CC0000"
  dict[ "LIGHTCOLOR" ] = "#F0EBD7"
  dict[ "DARKCOLOR" ] = "#B0C4DD"

  file = open( "page.html" )
  lines = file.readlines()
  file.close()

  ProcessLines( lines, dict ).printLines()


