#!/usr/bin/python

#    Kye - classic puzzle game
#    Copyright (C) 2005, 2006 Colin Phipps <cph@moria.org.uk>
#
#    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., 675 Mass Ave, Cambridge, MA 02139, USA.
#

from kye.frame import KFrame
from kye.game import KGame
from kye.common import tryopen, kyepaths, version
from kye.input import KyeRecordedInput
from kye.defaults import KyeDefaults

from random import Random
from string import upper
import sys
import gobject
import pickle
from gzip import GzipFile
from os.path import basename

def restartlevel(recordto = None, demo = None):
    global gamestate, recto, playback, g, playlevel
    gamestate = "starting level"
    recto = recordto
    playback = demo
    playlevel = g.thislev

def gotolevel(lname):
    global gamestate,playlevel
    gamestate = "starting level"
    playlevel = upper(lname)

def openfile(fname):
    global playfile,playlevel,gamestate
    playfile = fname
    playlevel = ""
    gamestate = "starting level"

def knownlevels():
    global playfile,defaults
    return defaults.get_known_levels(basename(playfile))

def dotick():
    global gamestate,g,recto,playlevel, playback
    if gamestate == "starting level":
        f.extra_title(None)
        # If recording this game, open the file to record to & tell the input system about it
        rng = Random()
        recfile = None
        if recto != None:
            try:
                recfile = GzipFile(recto, "w")
                recfile.write("Kye %s recording:\n" % version)
                recfile.write(basename(playfile) + "\n")
                recfile.write(playlevel + "\n")
                pickle.dump(rng.getstate(),recfile)
                recto = None
                f.extra_title("Recording")
            except IOError, e:
                f.error_message(message="Failed to write to "+recto)
                recfile = None
        f.moveinput.record_to(recfile)

        # If playing a demo, open it & read the header
        f.moveinput.clear()
        ms = f.moveinput
        if playback != None:
            try:
                instream = GzipFile(playback)
                header = instream.readline().rstrip()
                if header[0:4] == "Kye " and header[7:18] == " recording:":
                    fn = instream.readline().rstrip()
                    if fn != basename(playfile):
                        f.error_message(message="Recording is for "+fn+"; you must load this level set first")
                    else:
                        playlevel = instream.readline().rstrip()
                        rng.setstate(pickle.load(instream))
                        ms = KyeRecordedInput(instream)
                        f.extra_title("Replay")
                else:
                    f.error_message(message="This file is not a Kye recording")
                    print header[0:4]
                    print header[8:19]
            except IOError, e:
                f.error_message(message="Failed to read "+playback)
	    else:
                playback = None
        
        # Now try loading the actual level
	try:
	    gamefile = tryopen(playfile, kyepaths)
	    g = KGame(gamefile,lev = playlevel, movesource = ms, rng = rng)

            # Add current level name to window title
            f.level_title(g.thislev)
            # And remember that we have reached this level
            defaults.add_known(playfile,g.thislev)
            # Put hint in the status bar
	    f.stbar.update(hint=g.hint,levelnum=g.levelnum)
	except KeyError, e:
	    f.error_message(message="Level "+playlevel+" not known")
	except IOError, e:
	    f.error_message(message="Failed to read "+playfile)
	if g != None:
	    gamestate = "playing level"
	else:
	    gamestate = ""

    if gamestate == "playing level":
	if g.diamonds == 0:
	    gamestate="between levels"
	    msg = g.exitmsg
	    if f.moveinput.recordto != None:
		msg = "Recording complete."
            if f.moveinput != g.ms:
                msg = "Playback complete."
	    f.endleveldialog(g.nextlevel, msg)
	if gamestate == "playing level":
	    g.dotick()
	    f.canvas.game_redraw(g,g.invalidate)
	    f.stbar.update(diamonds=g.diamonds)
	    if g.thekye != None: f.stbar.update(kyes=g.thekye.lives)

    return True

defaults = KyeDefaults()
f = KFrame(opencall = openfile, restartcall = restartlevel, gotocall = gotolevel, knownlevscall = knownlevels, recentlevels = defaults.get_recent(), settings = defaults.settings)

playlevel = ""
if len(sys.argv)>1:
    playfile = sys.argv[1]
    if len(sys.argv)>2:
	playlevel = sys.argv[2]
else:
    playfile = "intro.kye"

gamestate = "starting level"
recto = None
playback = None

g = None
dotick()
gobject.timeout_add(100,dotick)

f.main()
f.moveinput.record_to(None)
defaults.save()
