#    Jools -- a graphical puzzle game in the Tetris tradition
#    
#    Copyright (C) 2002-2003 Paul Pelzl
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#

# highscore.py
#
# Display or add people to the high score list.
#

import os, pickle
import pygame
from initialize import *
from globals import *
import options


# Load the high scores from disk.  The high score file has the format:
# [ <jools version string>, [ [timedname1,timedlevel1,timedscore1], [timedname2,timedlevel2,timedscore2], ... ],
#        [ [untimedname1,untimedlevel1,untimedscore1], ...] ]
def loadScores():
   dummyFile = "~/.jools/scores"
   scoreFile = os.path.expanduser(dummyFile)
   # catch for OS's that don't implement $HOME
   if scoreFile == dummyFile:
      scoreFile = ".jools/scores"
   scoreFile = os.path.normpath(scoreFile)

   scores = [VERSION, [], []]
   # Check for existence of the jools high score file
   if os.path.exists(scoreFile):
      try:
         f = open(scoreFile, "r")
         scores = pickle.load(f)
         f.close()
      except:
         scores = [VERSION, [], []]
      # If the high score file is from a previous jools version, wipe it.
      if scores[0] != VERSION:
         scores = [VERSION, [], []]

   return (scores[1], scores[2])



# Save the high scores to disk.
def saveScores(scoreLists):
   dummyFile = "~/.jools/scores"
   scoreFile = os.path.expanduser(dummyFile)
   # catch for OS's that don't implement $HOME
   if scoreFile == dummyFile:
      scoreFile = ".jools/scores"
   scoreFile = os.path.normpath(scoreFile)

   dummyDir = "~/.jools"
   scoreDir = os.path.expanduser(dummyDir)
   # catch for OS's that don't implement $HOME
   if scoreDir == dummyDir:
      scoreDir = ".jools"
   scoreDir = os.path.normpath(scoreDir)

   # Check for existence of the directory
   if not os.path.isdir(scoreDir):
      os.mkdir(scoreDir)
   try:
      f = open(scoreFile, "w")
      try:
         pickle.dump([VERSION, scoreLists[0], scoreLists[1]], f)
      except:
         print "Error: Unable to serialize high score file."
      f.close()
   except IOError:
      print "Error: Unable to open high score file for writing."



# Check whether an entry belongs in the high score list.
def isHighScore(score, timeTrial):
   if score <= 0:
      return 0
   else:
      if timeTrial:
         scoreList = loadScores()[0]
      else:
         scoreList = loadScores()[1]
      if len(scoreList) >= 5:
         if score > scoreList[len(scoreList)-1][2]:
            return 1
         else:
            return 0
      else:
         return 1



# Compare two entries of a score list to determine their relative
# magnitude.  (Used within a sort() routine.)
def scoreCmp(entry1, entry2):
   if entry1[2] > entry2[2]:
      return -1
   elif entry1[2] < entry2[2]:
      return 1
   else:
      return 0



# Add a score to the high score list.  Return the rank
# of this score.
# "not timeTrial" is a shortcut.  If timeTrial == 1,
# then we want to look at the first scoreLists entry,
# i.e. 0.  (and vice versa.)
def addScore(name, level, points, timeTrial):
   thisScore = [name, level, points]

   scoreLists = loadScores()
   scoreLists[not timeTrial].append(thisScore)
   scoreLists[not timeTrial].sort(scoreCmp)

   rank = -1
   for i in range(len(scoreLists[not timeTrial])):
      if scoreLists[not timeTrial][i] == thisScore:
         rank = i
         break

   croppedScores = [scoreLists[0][:5], scoreLists[1][:5]]
   saveScores(croppedScores)
   return rank



# Display the high scores.  If the optional arguments are provided, then that
# number entry will be highlighted for the proper timed or untimed section.
def showScores(highlight=None, timeTrial=None):

   pygame.mouse.set_visible(1)

   # move the logo out of the way
   screen.blit(logoEraser, ((SCREENW-logoRect.width)/2, 0))
   screen.blit(logoImage, (0,0))

   color        = (0, 80, 255)
   specialColor = (40, 238, 252)

   titleText = highScoreTitleFont.render("High Scores", 1, (180, 180, 180), (1, 1, 1) )
   labelText = highScoreFont1.render(
      "Name                        Level            Score", 1, color, (1, 1, 1) )
   highScoreFont2.set_italic(1)
   timeText  = highScoreFont2.render("Time Trial", 1, color, (1, 1, 1) )
   notimeText= highScoreFont2.render("No Timer", 1, color, (1, 1, 1) )
   highScoreFont2.set_italic(0)
   clickText = highScoreFont2.render("(Click to Continue)", 1, (180, 180, 180), (1, 1, 1) )

   screen.blit(background, (0,100), (0,100,640,380))
   screen.blit(titleText,  (220, 100))
   screen.blit(labelText,  (160, 140))
   screen.blit(timeText,   (30,  220))
   screen.blit(notimeText, (35,  350))
   screen.blit(clickText, (240, 450))
   pygame.draw.line(screen, color, (10, 170), (630, 170), 5)
   pygame.draw.line(screen, color, (10, 300), (630, 300), 5)
   pygame.draw.line(screen, color, (10, 430), (630, 430), 5)
   pygame.draw.line(screen, color, (140, 170),(140, 430), 5)
   
   timedScores, untimedScores = loadScores()

   # time trial section
   for i in range(len(timedScores)):
      if i == highlight and timeTrial:
         c = specialColor
      else:
         c = color

      nameTemp = timedScores[i][0]
      if len(nameTemp) < 1:
         nameTemp = "<anonymous>"
      nameText = highScoreFont2.render(nameTemp, 1, c, (1, 1, 1) )
      screen.blit(nameText,  (160, 180+20*i))

      levelText = highScoreFont2.render(str(timedScores[i][1]), 1, c, (1, 1, 1) )
      screen.blit(levelText, (440, 180+20*i))

      scoreText = highScoreFont2.render(str(timedScores[i][2]), 1, c, (1, 1, 1) )
      screen.blit(scoreText, (595-scoreText.get_width(), 180+20*i))
   

   # untimed section
   for i in range(len(untimedScores)):
      if i == highlight and not timeTrial:
         c = specialColor
      else:
         c = color

      nameTemp = untimedScores[i][0]
      if len(nameTemp) < 1:
         nameTemp = "(anonymous)"
      nameText = highScoreFont2.render(nameTemp, 1, c, (1, 1, 1) )
      screen.blit(nameText,  (160, 310+20*i))

      levelText = highScoreFont2.render(str(untimedScores[i][1]), 1, c, (1, 1, 1) )
      screen.blit(levelText, (440, 310+20*i))

      scoreText = highScoreFont2.render(str(untimedScores[i][2]), 1, c, (1, 1, 1) )
      screen.blit(scoreText, (595-scoreText.get_width(), 310+20*i))

   pygame.display.update()
   pygame.display.flip()
   

   # Mouse button must be released, then pressed, then released again.
   pygame.event.pump()
   clickable = 0
   oldButtonPressed = 0
   while 1:
      if clickable:
         if oldButtonPressed:
            if not pygame.mouse.get_pressed()[0]:
               # center the logo again
               screen.blit(logoEraser, (0,0))
               screen.blit(logoImage, ((SCREENW-logoRect.width)/2, 0))
               return
         elif pygame.mouse.get_pressed()[0]:
            oldButtonPressed = 1

      else:
         if not pygame.mouse.get_pressed()[0]:
            clickable = 1

      pygame.event.pump()
      if pygame.event.wait().type == QUIT:
         options.saveOptions()
         pygame.quit()
         sys.exit("Exiting Jools...")


# arch-tag: high scores
