import pickle
import sys

from pygsear.Game import Game
from pygsear.Event import KEY_Event
from pygsear.Drawable import Drawable, Circle, RotatedImage
from pygsear.Widget import Dialog_LineInput, Dialog_OK
from pygsear.locals import RED, PI
from pygsear import conf

import pygame
from pygame.locals import K_w, K_a, K_d, K_s, K_SPACE, K_LEFT, K_RIGHT, K_UP, K_F1

import Architecture
from Architecture import Cell, Wall, Door, Level

TS = Architecture.TS

PROFILE = True

class Party(Drawable):
    def __init__(self):
        self.level = None
        self.coord = None
        self.facing = None
        self.characters = []
        self.see_distance = 5

    def add_character(self, character):
        self.characters.append(character)

    def enter_level(self, level):
        self.level = level
        self.coord = [0, 0]
        self.facing = 'north'

        if self.level.mode.startswith('topdown'):
            self.vis = RotatedImage(w=conf.game.level.layer, filename='party2.png', steps=4)
            self.update_vis()

            #self.remember = True
            self.remember = False
            cell = self.level.cells[tuple(self.coord)]
            if self.remember:
                cell.remembered = True

    def update_vis(self):
        x, y = self.coord
        dx, dy = x*TS, -y*TS
        vis = self.vis

        #vis.uclear()

        vis.center()
        vis.nudge(dx=dx, dy=dy)

        rotations = {'north': PI/2, 'east': 0, 'west': PI, 'south': 3*PI/2}
        vis.set_rotation(rotations[self.facing])
        vis.set_closest()

        #vis.udraw()
        conf.game.level.draw()

        self.crect = pygame.Rect(dx, dy, 10, 10)


    def face(self, facing):
        self.facing = facing

        if self.level.mode.startswith('topdown'):
            self.update_vis()

    def turn_right(self, ev=None):
        turns = {'north': 'east', 'east': 'south', 'west': 'north', 'south': 'west'}
        self.face(turns[self.facing])

    def turn_left(self, ev=None):
        turns = {'north': 'west', 'east': 'north', 'west': 'south', 'south': 'east'}
        self.face(turns[self.facing])

    def move_forward(self, ev=None):
        self.make_move()

    def make_move(self, direction=None):
        if direction is None:
            direction = self.facing

        if self.level is not None:
            block = self.level.cells[tuple(self.coord)].sides.get(direction, None)
            if block is None or block.passable or (block.door is not None and block.door.passable):
                move_func = getattr(self, '_move_%s' % direction)
                coord = self.coord[:]
                crect = pygame.Rect(self.crect)
                try:
                    move_func()
                    cell = self.level.cells[tuple(self.coord)]
                    print 'moved', direction, 'to', self.coord
                    if self.remember:
                        cell.remembered = True
                except KeyError:
                    self.coord = coord
                    self.crect = crect
                    print 'map error', coord
            else:
                print 'blocked', direction

        if self.level.mode.startswith('topdown'):
            if not self.vis.onscreen(layer=self.level.layer._window):
                print 'offscreen'
            self.update_vis()

    def _move_north(self):
        self.coord[1] += 1
        self.crect.top -= TS

    def _move_south(self):
        self.coord[1] -= 1
        self.crect.top += TS

    def _move_west(self):
        self.coord[0] -= 1
        self.crect.left -= TS

    def _move_east(self):
        self.coord[0] += 1
        self.crect.left += TS



class WixGame(Game):
    def initialize(self):
        self.set_background(color=(125, 125, 175))

        #cells = {   (0, 0): {'west': 'Wall', 'south': 'Wall',                          'north': 'Wall'},
        #                     (1, 0): {                'south': 'Wall', 'east': 'Wall',                },
        #                     (1, 1): {'west': 'Wall',                  'east': 'Wall', 'north': 'Door'},
        #                     (1, 2): {'west': 'Wall', 'south': 'Door', 'east': 'HDoor', 'north': 'Wall'},
        #                     (2, 2): {'west': 'Door', 'south': 'Wall',                 'north': 'Wall'},
        #                     (3, 2): {                'south': 'Wall',                 'north': 'Wall'},
        #                     (4, 2): {                'south': 'Door', 'east': 'Wall', 'north': 'Wall'},
        # 
        #                     (3, 1): {'west': 'Wall',                                  'north': 'Wall'},
        #                     (4, 1): {                                 'east': 'Wall', 'north': 'Door'},
        #                     (3, 0): {'west': 'Wall', 'south': 'Wall',                                },
        #                     (4, 0): {                'south': 'HDoor', 'east': 'Wall'                },
        # 
        #                     (4, -1): {                'south': 'Wall', 'east': 'Wall', 'north': 'HDoor'},
        #                     (3, -1): {'west': 'Wall', 'south': 'Wall',                                 },
        #         }

        #self.load_level(cells=cells)
        self.load_level('level0.wix')
        self.level.set_mode_topdown()

        self.events.add(KEY_Event(key=(K_w, K_a, K_d, K_s), on_press=self.nudge_map))

        self.party = Party()
        self.party.enter_level(self.level)
        self.level.layer.sprites.add(self.party.vis)
        self.events.add(KEY_Event(key=K_LEFT, on_press=self.party.turn_left))
        self.events.add(KEY_Event(key=K_RIGHT, on_press=self.party.turn_right))
        self.events.add(KEY_Event(key=K_UP, on_press=self.party.move_forward))

        #self.level.set_mode_topdown_full()
        self.level.set_mode_topdown_cansee(self.party)
        self.level.draw()

        self.events.add(KEY_Event(key=K_F1, on_press=self.do_load_level))

    def nudge_map(self, ev):
        directions ={   K_w: (0, 1),
                        K_a: (1, 0),
                        K_d: (-1, 0),
                        K_s: (0, -1)}

        k = ev.key
        d = directions[k]
        self.level.draw_area_nudge(d)

    def do_load_level(self, ev=None):
        level = self.level
        self.load_level()
        if level != self.level:
            self.level.set_mode_topdown()
            self.party.enter_level(self.level)
            self.level.layer.sprites.add(self.party.vis)
            self.level.set_mode_topdown_cansee(self.party)
            self.level.draw()

    def load_level(self, filename=None, cells=None):
        if hasattr(self, 'level'):
            oldlevel = self.level
        else:
            oldlevel = None

        level = Level()
        self.level = level

        if filename is None and cells is None:
            filename = Dialog_LineInput(message="Load File Name?", default="level.pickle").modal()

        if filename:
            try:
                level.load(filename, cells)
            except IOError:
                dlg = Dialog_OK(message="ERROR\n\nFile inaccessible: %s" % filename).modal()
                filename = None
            else:
                self.level_filename = filename

                if oldlevel is not None:
                    oldlevel.layer.kill()

        if filename is None:
            print 'erk. reverting to old level'
            self.level = oldlevel



def main():
    g = WixGame()

    if len(sys.argv) > 1 and sys.argv[1]:
        g.load_level(sys.argv[1])
        g.level.set_mode_topdown()
        g.party.enter_level(g.level)
        g.level.layer.sprites.add(g.party.vis)
        g.level.set_mode_topdown_cansee(g.party)
        g.level.draw()

    g.mainloop()



if __name__ == '__main__':
    if PROFILE:
        import hotshot, hotshot.stats
        prof = hotshot.Profile("pygsear.prof.log")
        prof.runcall(main)
        prof.close()
        stats = hotshot.stats.load("pygsear.prof.log")
        stats.strip_dirs()
        stats.sort_stats('time', 'calls')
        stats.print_stats(300)

    else:
        main()
