import cocos
import pyglet
from fov import fov
from npc import Npc
from policeman import Policeman
from note import Note
from math import sqrt
from dialogscene import DialogScene

class ItemLayer(cocos.layer.ScrollableLayer):

    is_event_handler = True

    def __init__(self, map_layer, note_layer, ui_layer):
        super(ItemLayer, self).__init__()

        self.dialog_scene = None
        self.map_layer = map_layer
        self.note_layer = note_layer
        self.ui = ui_layer
        self.player = None

        self.items = []
        for i in range(self.map_layer.map_size[0]):
            col = []
            for j in range(self.map_layer.map_size[1]):
                col.append([])
            self.items.append(col)


        self.police_warning = False

        self.target_killed = False

        self.ending = False

        self.gun_sfx =  pyglet.media.load("snd/shoot.ogg", streaming=False)

    def center_view(self, i, j):
        self.set_view(min(self.map_layer.map_size[0]*32-600,max(i*32+16-300,0)),\
                      min(self.map_layer.map_size[1]*32-600,max(j*32+16-300,0)),\
                      600,600)

    def propagate_alert(self, x, y):
        cell = self.map_layer.get_cell(x,y)
        if cell is None:
            return True
        for t in self.items[x][y]:
            if isinstance(t, Policeman):
                t.alert = True
        return not cell['transparent']

    def visit_cell(self, x, y):
        if self.map_layer is not None:
            cell = self.map_layer.get_cell(x,y)
            if cell is None:
                return True

            self.map_layer.set_cell_color(x, y, (255,255,255))
            for t in self.items[x][y]:
                t.update_visibility(True)
                if isinstance(t, Policeman)\
                    and t.alert :
                    if not self.police_warning:
                        self.police_warning = True
                        scene = DialogScene()
                        dialog = [['La Police :', '\"Stop right there!\"'],\
                                  ['Raoul V. :', '\"No! I vill not let you catch me!\"']]
                        scene.generate_dialogs(dialog)
                        cocos.director.director.push(scene)
                    t.chasing = True
            return not cell['transparent']

    def lose(self):
        scene = DialogScene()
        dialog = None
        if self.target_killed:
            dialog = [['La Police :', "\"Ve got you. Zis vill not end vell for you!\""],\
                    ['Raoul V. :', '\"Sacrebleu. So close. But at least I have killed him.\"'],\
                    ['La Police :', '\"Ha! Be happy while you still can.\"'],\
                    ['La Police :', '\"Ze guillotine avaits you for ze murder of Monsieur Jaures.\"'],\
                    ['', 'fin.']]
        else:
            dialog = [['La Police :', "\"Zat is enough! You are going to jail.\""],\
                    ['Raoul V. :', '\"Sapristi. I failed...\"'],\
                    ['La Police :', '\"Ve do not care, you have done too much as it iz.\"'],\
                    ['', 'fin.']]

        if dialog is not None:
            scene.generate_dialogs(dialog)
            scene.final = True
            cocos.director.director.push(scene)       

        self.ending = True

    def win(self):
        scene = DialogScene()
        dialog = [['', "After his crime, Raoul V. left Paris."],\
                ['', 'He had escaped the police.'],\
                ['', 'And the only thing he left behind was his name.'],\
                ['', 'Raoul Villain'],\
                ['', 'fin.'],\
                ['', 'fin..'],\
                ['', 'fin...'],\
                ['', 'fin... or is it?'],\
                ['', 'Well, three days after the murder, World War I started.'],\
                ['', 'It was brought forth by the shooting of this pacifist leader.'],\
                ['', 'With him dead, France decided to enter  war with Germany.'],\
                ['', 'Raoul Villain was caught, but eventually acquitted!'],\
                ['', 'If you want to know more...'],\
                ['', 'en.wikipedia.org - Raoul Villain'],\
                ['LD25 - Grungi Ankhfire', 'That is all folks, thank you for playing!'] ]


        scene.generate_dialogs(dialog)
        scene.final = True

        cocos.director.director.push(scene)       

        self.ending = True


    def kill_target(self):
    
        self.target_killed = True
        scene = DialogScene()
        dialog = [['Jean Jaures :', '\"Aaaaaaargh!\"'],\
                ['Raoul V. :', '\"I did it! Socialist scum.\"'],\
                ['Jean Jaures :', '\"Fool...\"'],\
                ['Jean Jaures :', '\"You vill... regret... zis...\"'],\
                ['Raoul V. :', '\"Ah! No, sir, for you are a villain.\"'],\
                ['Jean Jaures :', '\"No! You are ze villain!\"'],\
                ['Raoul V. :', '\"DIE!\"'],\
                ['', 'Raoul V. fires another shot. Then it is done.'],\
                ['Raoul V.', '\"Now, I need to escape ze city!\"']]
        
        scene.generate_dialogs(dialog)
        cocos.director.director.push(scene)       

    def do_frame(self, cur_cell):
        # Other entities movement
        to_update = []
        for i in range(self.map_layer.map_size[0]):
          for j in range(self.map_layer.map_size[1]):
            self.map_layer.set_cell_color(i, j, (50,50,50))
            for item in self.items[i][j]:
                item.update_visibility(False)
                to_update.append(item)
                if isinstance(item, Policeman):
                    if item.alert:
                        fov(i,j,5,self.propagate_alert, None)

        for t in to_update:        
            try:
                t.update()
            except AttributeError:
                pass

        # Field of view
        fov(cur_cell[0], cur_cell[1], 6, self.visit_cell, None)

        # Interactions
        to_remove = []
        for item in self.items[cur_cell[0]][cur_cell[1]]:
            if isinstance(item, Note):
                self.note_layer.label.element.text = item.text
                self.note_layer.visible = True
                self.ui.note_count -= 1
                self.ui.print_notes()
                to_remove.append(item)
                if item.info:
                    continue

                for i in range(self.map_layer.map_size[0]):
                    for j in range(self.map_layer.map_size[1]):
                        for n in self.items[i][j]:
                            if isinstance(n, Npc) or isinstance(n, Policeman):
                                if item.target == 'color':
                                    n.reveal_color(item.part, item.criteria)
                                elif item.target == 'shape':
                                    n.reveal_shape(item.part, item.criteria)


        for t in to_remove:
            self.remove(t)
            self.items[cur_cell[0]][cur_cell[1]].remove(t)                              

    def on_key_press(self, key, modifiers):
        if self.player is not None:
            cur_cell = self.player.pos
        else:
            return False

        # Inteface stuff
        
        if self.note_layer.visible == True:
            if key == pyglet.window.key.SPACE:
                self.note_layer.visible = False
            else:
                return

        if self.player.shooting:
            return

        # Player movement

        new_cell = cur_cell
        if  key == pyglet.window.key.UP:
            new_cell = cur_cell[0], cur_cell[1]+1
        elif  key == pyglet.window.key.DOWN:
            new_cell = cur_cell[0], cur_cell[1]-1
        elif  key == pyglet.window.key.LEFT:
            new_cell = cur_cell[0]-1, cur_cell[1]
        elif  key == pyglet.window.key.RIGHT:
            new_cell = cur_cell[0]+1, cur_cell[1]
 
        if new_cell != cur_cell and self.map_layer.is_passable(*new_cell):
            self.player.set_pos(*new_cell)
            self.items[cur_cell[0]][cur_cell[1]].remove(self.player)
            self.items[new_cell[0]][new_cell[1]].append(self.player)
            self.center_view(*new_cell)
            self.map_layer.center_view(*new_cell)
            cur_cell = new_cell

        if self.target_killed and\
            (cur_cell[0] == 0 or cur_cell[1] == 0 or\
            cur_cell[0] == self.map_layer.map_size[0]-1 or\
            cur_cell[1] == self.map_layer.map_size[1]-1):

            self.win()


        self.do_frame(cur_cell)

    def on_mouse_press(self, x, y, button, modifiers):



        selected_cell = self.map_layer.get_at_pixel(x, y)
        try:
            cell_pos = (selected_cell.x+self.map_layer.view_x)/32, (selected_cell.y+self.map_layer.view_y)/32
            for t in self.items[cell_pos[0]][cell_pos[1]]:
                if (isinstance(t, Npc) or isinstance(t, Policeman)) and t.sprites['head'].visible:
                    t.remove_from_layer(self)
                    self.gun_sfx.play()
                    self.items[cell_pos[0]][cell_pos[1]].remove(t)
                    self.player.ammo = max(self.player.ammo-1, 0)
                    self.ui.print_ammo(self.player.ammo)
                    if isinstance(t, Npc):
                        if t.is_target:
                            self.kill_target()

                    for i in range(self.map_layer.map_size[0]):
                        for j in range(self.map_layer.map_size[1]):
                            for item in self.items[i][j]:
                                if isinstance(item, Policeman) and\
                                    sqrt((i-cell_pos[0])**2+(j-cell_pos[1])**2) < 11:
                                    item.alert = True

        except AttributeError:
            print 'error...'
