import pygame
import os.path
from time import time
from gettext import gettext as _
 
from fortuneengine.GameEngineElement import GameEngineElement
 
from BattleEngine import BattleEngine
from Map import Map
from Room import Room
from Items import get_item
from constants import (
        MAP_PATH, ENV_PATH, ITEM_PATH, RIGHT, LEFT, NORTH, SOUTH, EAST,
        WEST, UNLOCKED_DOOR, LOCKED_DOOR, PUZZLE_DOOR, LOCKED_PUZZLE_DOOR,
        ENTRANCE_DOOR, EXIT_DOOR
        )
from JournalIntegration import do_load, load_dungeon_by_id
from fortuneengine.DrawableObject import DrawableObject
from fortuneengine.DynamicDrawableObject import DynamicDrawableObject
 
SEARCH_TIME = 2
COLOR_DELTA = 255/SEARCH_TIME
 
class Dungeon(GameEngineElement):
    def __init__(self, id):
        GameEngineElement.__init__(self, has_draw=True, has_event=True)
 
        self.id = id
        self.rooms={}
        self.__images={}
        self.__load_dungeon()
        self.__load_images()
        profile = self.game_engine.get_object('profile')
 
        if profile.position == (-1, -1):
            x,y = self.start
            profile.move_to( x, y )
 
 
 
        self.doorsList = []
 
        self.game_engine.get_scene().addObject(DrawableObject([self.__images['Room']], ''))
        self.doorsList.append(DrawableObject([self.__images['L']], '', True, 0 ,0))
        self.doorsList.append(DrawableObject([self.__images['F']], '', True, 360 ,0))
        self.doorsList.append(DrawableObject([pygame.transform.flip(self.__images['L'], True, False)], '', True, 990 ,0))
 
        #for door in self.doorsList: door.makeTransparent(True)
 
        self.add_to_scene(self.doorsList)
 
        self.itemsList = []
 
        for i in range(4):
            surf = pygame.Surface((10,10))
            surf.fill((0,0,0))
            tempItem = DrawableObject([surf],"", True)
            self.itemsList.append(tempItem)
 
        self.itemsList[0].setPosition(self.game_engine.art_scale(270, 1200, True), self.game_engine.art_scale(330, 900, False))
        self.itemsList[1].setPosition(self.game_engine.art_scale(100, 1200, True),self.game_engine.art_scale(600, 900, False))
        self.itemsList[2].setPosition(self.game_engine.art_scale(1100, 1200, True),self.game_engine.art_scale(600, 900, False))
        self.itemsList[3].setPosition(self.game_engine.art_scale(900, 1200, True),self.game_engine.art_scale(330, 900, False))
        self.add_to_scene(self.itemsList)
        self.add_to_engine()
 
    def add_to_engine(self):
        super(Dungeon, self).add_to_engine()
        self.game_engine.add_object('map', Map( self ) )
 
    def remove_from_engine(self):
        super(Dungeon, self).remove_from_engine()
        self.game_engine.get_object('map').remove_from_engine()
        self.game_engine.remove_object('map')
 
    def __load_dungeon(self):
        currentX=0
        currentY=0
 
        if os.path.exists( MAP_PATH + self.id ):
            dgnFile=open( MAP_PATH + self.id,'r')
            d_dict = do_load( dgnFile )
            dgnFile.close()
        else:
            d_dict = load_dungeon_by_id( self.id )
 
        self.sizeX = d_dict['x']
        self.sizeY = d_dict['y']
        self.theme = d_dict['theme']
        self.name = d_dict['name']
        self.next = d_dict['next']
 
        for line in d_dict['roomstr']:
            the_room = Room( currentX, currentY, line )
            self.rooms[(currentX,currentY)] = the_room
 
            if the_room.is_entrance():
                self.start=(currentX,currentY)
 
            currentX+=1
            if currentX==self.sizeX:
                currentY+=1
                currentX=0
 
            if currentY>self.sizeY:
                break
 
 
    def __load_images(self):
        #LVL_PATH = ENV_PATH + "ice/"
        #LVL_PATH = ENV_PATH + "celestial/"
        LVL_PATH = ENV_PATH + "pyramid/"
 
        for img_key in ['Room','F','L']:
            img = pygame.image.load(LVL_PATH+img_key+".png").convert()
            img.set_colorkey((255,0,255))
            width,height = img.get_size()
 
            img = pygame.transform.scale(img, (self.game_engine.art_scale(width, 1200, True), self.game_engine.art_scale(height, 900, False)))
 
            self.__images[img_key] = img
 
    def get_current_room(self):
        profile = self.game_engine.get_object('profile')
        return self.rooms[profile.position]
 
    def move_permissions(self, door_type):
        if door_type == UNLOCKED_DOOR:
            return True
 
        elif door_type == LOCKED_DOOR:
            #Checks if they have a small key
            for item in self.game_engine.get_object('profile').inventory:
                # Search for small key (ID: 'q')
                if item.id == 'q':
                    self.game_engine.get_object('mesg').add_line(
                        _("You use a SMALL KEY"))
                    return True
 
            self.game_engine.get_object('mesg').add_line(
                _("This door is locked, you need a SMALL KEY"))
            return False
 
        elif door_type == PUZZLE_DOOR or door_type == LOCKED_PUZZLE_DOOR:
            #TODO: START PUZZLE
            return False
 
        elif door_type == ENTRANCE_DOOR:
            self.game_engine.get_object('mesg').add_line(
                _("There is no turning back now"))
            return False
 
        elif door_type == EXIT_DOOR:
            #Checks if they have a big key
            for item in self.game_engine.get_object('profile').inventory:
                # Search for big key (ID: 'r')
                if item.id == 'r':
                    self.game_engine.get_object('mesg').add_line(
                        _("You use the BIG KEY, and the door slams behind you!"))
                    return True
 
 
            self.game_engine.get_object('mesg').add_line(
                _("This door is locked, you need a BIG KEY"))
            return False
 
        return False
 
 
    def move_forward(self):
        profile = self.game_engine.get_object('profile')
        x,y = profile.position
 
        if profile.playerFacing == NORTH:
            dX = x
            dY = y - 1
            dc = 'N'
 
        elif profile.playerFacing == SOUTH:
            dX = x
            dY = y + 1
            dc = 'S'
 
        elif profile.playerFacing == EAST:
            dX = x + 1
            dY = y
            dc = 'E'
 
        elif profile.playerFacing == WEST:
            dX = x - 1
            dY = y
            dc = 'W'
 
 
 
        door_flag = self.rooms[profile.position].get_door( dc )
        if door_flag == EXIT_DOOR or door_flag == ENTRANCE_DOOR:
            if self.move_permissions( door_flag ):
                self.game_engine.get_object('profile').next_dungeon()
 
        elif self.rooms.has_key( (dX, dY) ):
            if self.move_permissions( door_flag ):
                self.game_engine.get_object('mesg').add_line(_("You enter room at %i,%i")%(dX, dY))
                profile.move_to( dX, dY )
                self.game_engine.get_object('map').update_macro()
                self.check_for_enemies()
        else:
            #On a border of the grid
            pass
 
    def check_for_enemies(self):
        current_room = self.get_current_room()
        if current_room.has_enemy:
            self.game_engine.add_object('battle', BattleEngine( self ) )
 
    def item_pickup(self):
        profile = self.game_engine.get_object('profile')
        current_room = self.rooms[profile.position]
 
        for i in range( 0, 4 ):
            item_key = current_room.get_item( i )
 
            # If visible, remove from room and place in players inventory
            if item_key[0] != '0' and item_key[1] == 'v':
                item = get_item( item_key[0] )
                profile.give_item( item )
                current_room.remove_item( i )
                self.game_engine.get_object('mesg').add_line(_("%s discovered!")% item.name)
                return
        self.game_engine.get_object('mesg').add_line(_("No items found."))
 
    def amulet_search(self):
        current_room = self.get_current_room()
 
        found = False
        for i in range( 0, 4 ):
            item_key = current_room.get_item( i )
 
            # If visible, remove from room and place in players inventory
            if item_key[0] != '0' and item_key[1] == 'h':
                current_room.set_item( i, item_key[0], 'v' )
                found = True
        if found:
            self.game_engine.get_object('mesg').add_line(_("Amulet Search has revealed new items."))
        else:
            self.game_engine.get_object('mesg').add_line(_("Amulet search found nothing."))
 
    def search_timer_handler(self):
        """
        Called when the timer has expired, fires off the amulet search
        """
        self.game_engine.stop_event_timer( \
            self.search_timer_handler )
        del self.pickup_time
        self.amulet_search()
 
    def event_handler(self, event):
        if event.type == pygame.KEYDOWN:
            newKey=pygame.key.name(event.key)
 
            if newKey=='[4]' or newKey=='left':
                self.game_engine.get_object('profile').turn( LEFT )
                return True
 
            elif newKey=='[6]' or newKey=='right':
                self.game_engine.get_object('profile').turn( RIGHT )
                return True
 
            elif newKey=='[8]' or newKey=='up':
                self.move_forward()
                return True
 
            elif newKey=='[1]' or newKey=='e':
                self.pickup_time = time()
                self.game_engine.start_event_timer( \
                    self.search_timer_handler, SEARCH_TIME * 1000 )
                return True
 
        elif event.type == pygame.KEYUP:
            newKey=pygame.key.name(event.key)
 
            if newKey=='[1]' or newKey=='e':
                if hasattr( self, 'pickup_time' ):
                    if time() - self.pickup_time < SEARCH_TIME:
                        self.item_pickup()
 
                    self.game_engine.stop_event_timer( \
                        self.search_timer_handler )
                    del self.pickup_time
                return True
 
    def normalize_dir( self ):
        profile = self.game_engine.get_object('profile')
        dir = profile.playerFacing
 
        if dir == NORTH:
            return 'W', 'N', 'E'
 
        elif dir == SOUTH:
            return 'E', 'S', 'W'
 
        elif dir == EAST:
            return 'N', 'E', 'S'
 
        elif dir == WEST:
            return 'S', 'W', 'N'
 
    def draw(self):
        profile = self.game_engine.get_object('profile')
        dir = profile.playerFacing
        current_room = self.rooms[profile.position]
 
        # Draw Room Doors
        left, front, right = self.normalize_dir()
        if current_room.get_door( left ) != '0':
            self.doorsList[0].makeTransparent(False)
        else:
            self.doorsList[0].makeTransparent(True)
 
        if current_room.get_door( front ) != '0':
            self.doorsList[1].makeTransparent(False)
        else:
            self.doorsList[1].makeTransparent(True)
 
        if current_room.get_door( right ) != '0':
            self.doorsList[2].makeTransparent(False)
        else:
            self.doorsList[2].makeTransparent(True)
 
        # Draw Items
        img_list = []
 
        cnt = 0
        for i in range( dir, (dir + 4) ):
            #imod for room rotation
            imod = i % 4
 
            item_key = current_room.get_item( imod )
 
            if item_key[0] == '0' or item_key[1] != 'v':
                self.itemsList[cnt].makeTransparent(True)
            else:
                self.itemsList[cnt].repopulateImages([pygame.image.load(ITEM_PATH + get_item( item_key[0] ).path)])
                self.itemsList[cnt].makeTransparent(False)
 
            cnt += 1
 
            #if not self.__images.has_key( path ):
                #img = pygame.image.load(ITEM_PATH + path).convert()
                #width,height = img.get_size()
                #img = pygame.transform.scale(img, (self.game_engine.art_scale(width, 1200, True), self.game_engine.art_scale(height, 900, False)))
                #self.__images[path] = img
 
            #img_list.append( self.__images[path] )
 
        #Amulet Search Function
        # if hasattr(self, 'pickup_time'):
#             elp = time() - self.pickup_time
#             color_a = int(elp*COLOR_DELTA)
#             if color_a > 255:
#                 color_a = 255
#                 self.game_engine.stop_event_timer(self.search_timer_handler)
#             surf1 = pygame.Surface((self.game_engine.width,self.game_engine.height), pygame.SRCALPHA)
#             pygame.draw.rect(surf1, (255, 255, 255, color_a), (0, 0, self.game_engine.width, self.game_engine.height))
#             screen.blit( surf1, (0, 0) )