"""
------------------------------------------------------------------------------
--                                                                          --
--                                 LAB 05                                   --
--                                                                          --
--                             L A B 0 5 . P Y                              --
--                                                                          --
------------------------------------------------------------------------------
-- <Your Name Here>                                                         --
--                                                                          --
-- <Class Name Here>                                                        --
--                                                                          --
------------------------------------------------------------------------------
-- This file contains a simple Zelda demo and an implementation of          --
-- The Ackermann function.                                                  --
--                                                                          --
------------------------------------------------------------------------------
"""

from Tkinter import *
import Frames

class AnimatedSprite:
    directions = {
        'North' : 1,
        'South' : 2, 
        'East' : 4,
        'West' : 8 
    }

    def reset_animation(self):
        self.current = 0
        self.image = self.frames[self.current_set][0]

    def __init__(self, frames, x=0, y=0):
        self.frames = frames
        self.current_set = 0
        self.reset_animation()
        self._moving = 0
        self.x = x
        self.y = y

    def moving(self):
        return self._moving > 0

    def __getitem__(self, key):
        if (type(key) != str and type(key) != unicode) or key not in AnimatedSprite.directions:
            raise IndexError, 'Index for Sprite must be a valid direction'

        return bool(self._moving & AnimatedSprite.directions[key])

    def __setitem__(self, key, value):
        if (type(key) != str and type(key) != unicode) or key not in AnimatedSprite.directions:
            raise IndexError, 'Index for Sprite must be a valid direction'

        if type(value) != bool:
            raise TypeError, 'Value for a direction can only be True or False'

        if value:
            self._moving = self._moving | AnimatedSprite.directions[key]
        else:
            self._moving = self._moving & ~AnimatedSprite.directions[key]

    def update_frame(self):
        curr_set = 1

        if self['South']:
            curr_set = 0
        elif self['North']:
            curr_set = 2
        elif self['East']:
            curr_set = 3

        if curr_set != self.current_set:
            self.current = 0
            self.current_set = curr_set
        else:
            self.current = self.current + 1

        if self.current == len(self.frames[self.current_set]):
            self.current = 0

        self.image = self.frames[self.current_set][self.current]

    def set_frame(self, num):
        self.current = num
        self.image = self.frames[self.current_set][self.current]


class World(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        Pack.config(self)

        self.world_map = Canvas(self, width=640, height=480)
        self.world_map.pack()

        frame_sets = []
        for binaries in Frames.link_sets:
            frames = []
            for binary in binaries:
                frames += [PhotoImage(data = binary)]
            frame_sets += [frames]

        self.link = AnimatedSprite(frame_sets, 250, 250)
        self.stop_counter = 0
        self.sprite = self.world_map.create_image(self.link.x, self.link.y, image = self.link.image)

        self.bind_all('<KeyPress>', self.onKeyPress)
        self.bind_all('<KeyRelease>', self.onKeyRelease)
        self.after(10, World.update, self)

    def update(self):
        self.world_map.delete(self.sprite)
        if self.link.moving():
            self.link.update_frame()

            if self.link['North']:
                self.link.y -= 3
                if self.link.y < -64:
                    self.link.y = int(self.world_map.cget('height')) + 20

            if self.link['South']:
                self.link.y += 3
                if self.link.y > int(self.world_map.cget('height')) + 32:
                    self.link.y = -84

            if self.link['East']:
                self.link.x += 3
                if self.link.x > int(self.world_map.cget('width')) + 24:
                    self.link.x = -68

            if self.link['West']:
                self.link.x -= 3
                if self.link.x < -48:
                    self.link.x = int(self.world_map.cget('width')) + 20

            self.stop_counter = 0
        elif self.stop_counter > 3:
            self.stop_counter = 0
            self.link.reset_animation()
        else:
            self.stop_counter = self.stop_counter + 1

        self.sprite = self.world_map.create_image(self.link.x, self.link.y, image = self.link.image)

        self.after(42, World.update, self)

    def onKeyPress(self, event):
        if event.char == 'w':
            self.link['South'] = True
        elif event.char == 'a':
            self.link['North'] = True
        elif event.char == 's':
            self.link['East'] = True
        elif event.char == 'd':
            self.link['West'] = True

    def onKeyRelease(self, event):
        if event.char == 'w':
            self.link['South'] = False
        elif event.char == 'a':
            self.link['North'] = False
        elif event.char == 's':
            self.link['East'] = False
        elif event.char == 'd':
            self.link['West'] = False

##Add Ackermann's function here

##Ackermann's function should be before here

if __name__ == '__main__':
    world = World()

    world.mainloop()
