#!/usr/bin/env python
#
#    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
#

# __init__.py
#
# Primary game control loop.
#

import os, random, sys

try:
   import pygame
except ImportError:
   sys.exit("Jools requires Pygame, which does not appear to be installed.")


from pygame.locals import *

from globals import *
from joolsutils import *

from initialize import *
import intro, options, grid, highscore, inputbox, playlist, scoreboard


def gameExit():
   options.saveOptions()
   pygame.quit()
   sys.exit("Exiting Jools...")



joolsClock = pygame.time.Clock()

# djk: musicMode is which music we're currently
#      playing.  Useful so we don't restart the
#      same song eg. between levels / from high
#      score screen to title, etc.
#      0 = music off
#      1 = title / highscore
#      2 = time trial
#      3 = untimed
musicMode = playlist.OFF

optionsList = options.loadOptions()
if len(optionsList) == 5:
   audio.soundEnabled    = optionsList[0]
   audio.musicEnabled    = optionsList[1]
   audio.soundMultiplier = optionsList[2]
   audio.musicMultiplier = optionsList[3]
   audio.soundSet        = optionsList[4]
   options.setSoundVolume(audio.soundMultiplier)
   options.switchSoundSet()



# Handle initial player configuration, game choice, etc.
while 1:

   # Create an empty grid
   joolsGrid = grid.Grid()

   # Create a scoreboard
   pointsDisplay = scoreboard.Scoreboard()

   # djk: start titlescreen music
   if musicMode != playlist.TITLE:
      musicMode = playlist.TITLE
      joolsPlaylist.playNext(musicMode)


   # center the logo image
   screen.blit(logoEraser, (0,0))
   screen.blit(logoImage, ((SCREENW-logoRect.width)/2,0))

   timeTrial = intro.showIntro()

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

   gameOver = 0
   level = 1
   getNewTrack = 1
   timerCorrection = 2.0
   joolsGrid.totalPoints = 0
   joolsGrid.joolsThisLevel = 0
   joolsGrid.totalJools  = 0
   
   # Play a complete game with levels, etc.
   while not gameOver:
      
      # djk: start the music, based on game mode
      if getNewTrack:
         if timeTrial:
            musicMode = playlist.TIMED
            joolsPlaylist.playNext(musicMode)
         else:
            musicMode = playlist.UNTIMED
            joolsPlaylist.playNext(musicMode)
      

      # draw the scoreboard and audio status
      pointsDisplay.drawBoard()
      pointsDisplay.setLevel(level)
      pointsDisplay.setPoints(joolsGrid.totalPoints)
      pointsDisplay.setJoolsCleared(joolsGrid.totalJools, level)
      audioDisplay.draw()
      

      # start the game (let the jools fall)
      joolsGrid.new(timeTrial)  # Fill empty grid with jools
      while joolsGrid.updateAll(UPDATEFALLING):
         pygame.event.pump() 
         if pygame.event.peek(QUIT):
            gameExit()
         pygame.event.get()  # Clear the event queue
         # Throttle the framerate a bit as the jools fall
         joolsClock.tick(FALLING_TARGET_FPS)
         joolsGrid.cleanUpdated()
         joolsGrid.renderUpdated()
         #pygame.display.flip()
      getNewGrid = 0


      # Main game loop
      gridIsOld = 0     # Points should be tallied only if the "grid is old",
                        # after the fresh grid has settled and initial matches have
                        # been removed.
      while not getNewGrid and not gameOver:
         # Remove jools and let them fall
         matches = joolsGrid.getMatches(gridIsOld)
         while len(matches) > 0:
            pointsDisplay.setPoints(joolsGrid.totalPoints)
            pygame.display.flip()
            if timeTrial:
               joolsGrid.timer.boost(timerCorrection*float(joolsGrid.pointsToAdd))
            joolsGrid.removeJools(matches, gridIsOld)
            pointsDisplay.setJoolsCleared(joolsGrid.totalJools, level)
            pygame.display.flip()

            while joolsGrid.updateAll(UPDATEFALLING) and not gameOver:
               pygame.event.pump()
               if pygame.event.peek(QUIT):
                  gameExit()
               pygame.event.get()  # Clear the event queue
               # Throttle the framerate a bit as the jools fall
               joolsClock.tick(FALLING_TARGET_FPS)
               joolsGrid.cleanUpdated()
               joolsGrid.renderUpdated()
               #pygame.display.flip()
            matches = joolsGrid.getMatches(gridIsOld)

         gridIsOld = 1

         if joolsGrid.joolsThisLevel >= JOOLS_PER_LEVEL:
            # New level!
            joolsGrid.joolsThisLevel = 0
            level += 1
            if timeTrial:
               joolsGrid.timer.timer_dec += TIMER_DECREMENT_MOD
            pointsDisplay.setLevel(level)
            pygame.display.flip()

            getNewGrid = 1
            getNewTrack = 1
            screen.blit(levelUpImage, (SCREENW-(8*JOOLSIZE) + ((8*JOOLSIZE)-levelUpRect.width)/2, 
               (SCREENH-(8*JOOLSIZE) + ((8*JOOLSIZE)-levelUpRect.height)/2)))
            pygame.display.update()
            levelup.play()
            # fade out the music while displaying the "level up" graphic
            if audio.Capable and audio.musicEnabled:
               pygame.mixer.music.fadeout(1500)
            pygame.time.wait(1500)
            screen.blit(background, (SCREENW-(8*JOOLSIZE), SCREENH-(8*JOOLSIZE)))

         # Process input (Most of the cycles go here)
         if not getNewGrid:
            joolsGrid.updateMoves()
            pointsDisplay.setAvailableMoves(len(joolsGrid.availableMoves))
            pygame.display.flip()
            if len(joolsGrid.availableMoves) > 0:
               while not (joolsGrid.hasSwaps) and not gameOver:
                  pygame.event.pump()
                  if pygame.event.peek([QUIT]):
                     gameExit()
                  if joolsGrid.processInput():
                     gameOver = 1
                  pygame.event.get()  # clear the event queue
                  # Throttle the framerate a bit on rotations
                  joolsClock.tick(ROTATING_TARGET_FPS)
                  if timeTrial:
                     joolsGrid.timer.tick()
                  if timeTrial and joolsGrid.timer.time <= 0.0:
                     gameOver = 1
                  if joolsGrid.updateAll(UPDATEROTATION):
                     #pygame.time.wait(ROTATIONDELAY)
                     joolsGrid.cleanUpdated()
                     joolsGrid.renderUpdated()

               runTimer = 0
               if joolsGrid.hasFalseSwaps:
                  runTimer = 1
               # Handle jool swapping
               while joolsGrid.updateAll(UPDATESWAPS) and not gameOver:
                  pygame.event.pump()
                  if pygame.event.peek(QUIT):
                     gameExit()
                  pygame.event.get()
                  # Throttle the framerate a bit on jool swapping
                  joolsClock.tick(SWAPPING_TARGET_FPS)
                  # If the jools are being swapped illegally,
                  # then the clock still runs.
                  if timeTrial and runTimer:
                     joolsGrid.timer.tick()
                  joolsGrid.cleanUpdated()
                  joolsGrid.renderUpdated()
                  #pygame.display.flip()
            else:
               # No moves remaining!
               if timeTrial:
                  getNewGrid = 1
                  getNewTrack = 0
                  screen.blit(noMovesImage, (SCREENW-(8*JOOLSIZE) + ((8*JOOLSIZE)-noMovesRect.width)/2, 
                     (SCREENH-(8*JOOLSIZE) + ((8*JOOLSIZE)-noMovesRect.height)/2)))
                  pygame.display.update()
                  pygame.time.wait(1500)
                  screen.blit(background, (640-(8*JOOLSIZE), 480-(8*JOOLSIZE)))
               else:
                  # first display "no moves"...
                  screen.blit(noMovesImage, (SCREENW-(8*JOOLSIZE) + ((8*JOOLSIZE)-noMovesRect.width)/2, 
                     (SCREENH-(8*JOOLSIZE) + ((8*JOOLSIZE)-noMovesRect.height)/2)))
                  pygame.display.update()
                  pygame.time.wait(1000)
                  # ...then draw the jools back on the screen,
                  # effectively erasing the "no moves" message...
                  joolsGrid.updateAll(UPDATEREDRAW)
                  joolsGrid.cleanUpdated()
                  joolsGrid.renderUpdated()
                  pygame.time.wait(1000)
                  # ...then proceed with "game over" message.
                  gameOver = 1

   
   screen.blit(gameOverImage, (SCREENW-(8*JOOLSIZE) + ((8*JOOLSIZE)-gameOverRect.width)/2, 
      (SCREENH-(8*JOOLSIZE) + ((8*JOOLSIZE)-gameOverRect.height)/2)))
   pygame.display.update()


   # Is this a high score?
   if highscore.isHighScore(joolsGrid.totalPoints, timeTrial):

      # Add a hint of suspense
      pygame.time.wait(1000)

      HSImageLocation = (SCREENW-(8*JOOLSIZE) + ((8*JOOLSIZE)-highScoreRect.width)/2,
         SCREENH-(8*JOOLSIZE) + ((8*JOOLSIZE)-gameOverRect.height)/2 + gameOverRect.height - 30)
      screen.blit(highScoreImage, HSImageLocation)
      pygame.display.update()
      
      boxLocation = (HSImageLocation[0] + highScoreRect.width/2, HSImageLocation[1] + highScoreRect.height + 15)
      name = inputbox.ask(screen, (200,200,200), (1,1,1), " Name", boxLocation)

      rank = highscore.addScore(name, level, joolsGrid.totalPoints, timeTrial)
      highscore.showScores(rank, timeTrial)

      # djk: start titlescreen music
      if musicMode != playlist.TITLE:
         musicMode = playlist.TITLE
         joolsPlaylist.playNext(musicMode)


   else:
      if audio.Capable and audio.musicEnabled:
         pygame.mixer.music.fadeout(4000)
      pygame.time.wait(4000)

      # djk: start titlescreen music
      if musicMode != playlist.TITLE:
         musicMode = playlist.TITLE
         joolsPlaylist.playNext(musicMode)



# arch-tag: mainloop for jools
