# pygsear
# Copyright (C) 2003 Lee Harr
#
#
# This file is part of pygsear.
#
# pygsear 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.
#
# pygsear 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 pygsear; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


import sys
import os
import cPickle

import pygame
from pygame.locals import K_BACKSPACE, K_RETURN

from pygsear.Game import Game
from pygsear.Drawable import Multi, Circle, String
from pygsear.Widget import SpriteButton, Dialog_LineInput
from pygsear.Event import MOUSEBUTTONDOWN_Event, KEYUP_Event
from pygsear.Util import load_image, scale_image
from pygsear.locals import LBLUE, GREEN
from pygsear import conf


class Dot(Multi):
    """Dot for connecting in the connect-the-dots game.

    Combines a point for lines to connect between, and a
    related symbol by which the dots should be ordered.
    At this time the symbols are just sequential integers.

    """

    def __init__(self, location, dot_num):
        """Initialize the dot.

        @param location: initial position for the dot
            part of the dot.
        @param dot_num: identifier for this dot.

        """

        Multi.__init__(self)
        self.set_position(location)
        self.dot_num = dot_num

    def __repr__(self):
        return 'Dot number ' + str(self.dot_num)

    def set_next_dot(self, dot):
        self.next_dot = dot

    def set_game(self, game):
        self.game = game

    def got_clicked(self, *args):
        #print self.dot_num, 'got clicked'
        self.game.click_dot(self)

    def set_first(self):
        self.first = 1

    def is_first(self):
        if hasattr(self, 'first'):
            return True
        else:
            return False

    def set_last(self):
        self.last = 1

    def is_last(self):
        if hasattr(self, 'last'):
            return True
        else:
            return False

class DotGame(Game):
    def __init__(self, game_name):
        self.game_name = game_name
        Game.__init__(self)

    def initialize(self):
        self.previous = None
        self.current = None
        self.load_game()
        self.load_picture()

    def load_game(self):
        #os.chdir(self.game_name)

        filename = 'data/dots/%s_dots.pickle' % self.game_name

        f = file(filename)
        dot_locations = cPickle.load(f)
        self.number_dots(dot_locations)

    def load_picture(self, image_name=None):
        if image_name is None:
            for ext in ['png', 'tga']:
                try:
                    image_name = '%s_picture.%s' % (self.game_name, ext)
                    self.image = load_image(image_name, convert=0)
                except pygame.error:
                    #raise
                    #print 'failed', image_name
                    continue
                else:
                    return
            raise pygame.error, "Unable to load image"

        else:
            self.image = load_image(image_name, convert=0)


    def show_picture(self):
        self.picture = scale_image(self.image, conf.WINWIDTH, conf.WINHEIGHT)
        self.set_background(img=self.picture)

    def random_dots(self):
        points = []
        for i in range(20):
            c = Circle()
            c.set_positionRandom()
            points.append(c.get_position())
        return points

    def number_dots(self, dot_locations):
        dot = None
        dot_num = 0
        for dot_location in dot_locations:
            dot_num += 1
            x, y = dot_location
            new_dot = self.make_dot(x, y, dot_num)
            if dot is not None:
                dot.set_next_dot(new_dot)
            else:
                new_dot.set_first()
            dot = new_dot
        dot.set_last()

    def make_dot(self, x, y, dot_num):
        d = Dot((x, y), dot_num)

        c = Circle(radius=3, color=LBLUE)
        button = SpriteButton(sprite=c, callback=d.got_clicked)
        self.events.add(button.events)
        d.addSprite(button)

        symbol = String(message=str(dot_num), fontSize=20)
        button = SpriteButton(symbol, d.got_clicked)
        self.events.add(button.events)
        d.addSprite(button, xOffset=10, yOffset=10)

        d.set_game(self)
        self.sprites.add(d)

        return d

    def set_current(self, dot):
        self.previous = self.current
        self.current = dot
        #print 'From', self.previous, 'to', self.current

    def check_next(self, dot):
        #print dot.next_dot
        if self.current is None and dot.is_first():
            return True
        elif self.current is None:
            return False
        elif hasattr(self.current, 'next_dot') and self.current.next_dot == dot:
            return True
        else:
            return False

    def click_dot(self, dot):
        if self.check_next(dot):
            if not dot.is_first():
                self.connect_to_dot(dot)
            self.set_current(dot)

            if dot.is_last():
                self.show_picture()

    def connect_to_dot(self, dot):
        x1, y1 = self.current.get_position()
        x2, y2 = dot.get_position()
        dirty = pygame.draw.line(self.window.screen, GREEN, (x1, y1), (x2, y2))
        pygame.display.update(dirty)


class DotGameMaker(DotGame):
    def initialize(self):
        self.set_background(color=(40, 60, 140))

        self.dots = []

        self.events.add(MOUSEBUTTONDOWN_Event(button=1, callback=self.click))
        self.events.add(KEYUP_Event(key=K_BACKSPACE, callback=self.oops))
        self.events.add(KEYUP_Event(key=K_RETURN, callback=self.save))

    def save(self, pygame_event=None):
        print 'saving'
        self.input2 = Dialog_LineInput(message='Name of game:',
                    callback=self.write)
        self.input2.modal()

    def write(self, game_name):
        #print 'save as', filename
        #print 'dots', self.dots
        self.game_name = game_name

        os.chdir('data/images')
        filename = '%s_picture.tga' % game_name
        pygame.image.save(self.bg, filename)
        os.chdir('../dots')
        filename = '%s_dots.pickle' % game_name
        f = file(filename, 'w')
        dots = [dot.position for dot in self.dots]
        cPickle.dump(dots, f)
        f.close()

    def click(self, pygame_event):
        x, y = pygame_event.pos
        d = self.make_dot(x, y, len(self.dots)+1)
        print 'adding', d
        self.dots.append(d)

    def oops(self, pygame_event=None):
        if self.dots:
            d = self.dots.pop()
            print 'removing', d
            self.sprites.remove(d)
            d.kill()

    def set_current(self, foo):
        pass

    def click_dot(self, dot):
        pass


if __name__ == '__main__':
    if len(sys.argv) > 2:
        image_name = sys.argv[2]
        g = DotGameMaker(None)
        g.load_picture(image_name)
        g.show_picture()

    elif len(sys.argv) > 1:
        game_name = sys.argv[1]
        g = DotGame(game_name)

    else:
        g = DotGame('default')

    g.mainloop()



