#!/usr/local/bin/python2.7
"""Game Map Editor"""
"""Adventures on Planet Zephulor by Aaron Hachez. 

   All code, artwork, and sound copyright 2003, Aaron Hachez.

   ----------------------------------------------------------------------------------------

   This file is part of "Adventures on Planet Zephulor".

   A copy of the GNU General Public License should be included with any
   redistribution of this program in a file named "COPYING.txt".

   "Adventures on Planet Zephulor" 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.

   "Adventures on Planet Zephulor" 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 "Adventures on Planet Zephulor"; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

   ----------------------------------------------------------------------------------------

   "Adventures on Planet Zephulor" uses the following libraries:

   PyGame
   SDL

   Both are at the time of this writing, licensed under the GNU LGPL. Please see
   the included file LGPL for details 
"""

# init the SDL window
import pygame
import os
import sys
import string
from pygame.locals import *
from game_entities import *
from game_map import *
from tilemenu import *
from charmenu import *
from domenu import *
from hud import *
from keymap import *
from myimg import *

if not pygame.font: print 'Warning, fonts disabled'
if not pygame.mixer: print 'Warning, sound disabled'

screenwidth = 800
screenheight = 600

pygame.init()
screen = pygame.display.set_mode((screenwidth, screenheight))
pygame.display.set_caption('Game Map Tool')
#pygame.mouse.set_visible(0)

background = pygame.Surface(screen.get_size())
background = background.convert()
background.fill((255, 255, 255))

# This is a tmp function
def make_bkg(text="Some text."):
    """Print some text."""
    if pygame.font:
        font = pygame.font.Font(None, 36)
        text = font.render(text, 1, (210, 210, 210))
        textpos = text.get_rect()
        textpos.centerx = background.get_rect().centerx
        background.fill((0, 0, 0))
        background.blit(text, textpos)

class mouse:
    """Basic mouse class"""

    screenrect = []

    width = 32
    height = 32

    mousestate = []

    # This is used to display an image associated with the mouse pointer
    mouseimage = None

    # The currently selected character
    charbuffer = None

    # The currently selected tile
    tileselected = 0

    # The attributes of the currently selected tile
    tileattributes = []

    # Whether or not the mouse button is down or up (Default up)
    up = 1
    down = 0

    # The tile we are over
    tileover = 0

    def __init__(self):
        self.mousestate = [0, 0, 0]
        self.screenrect = [0, 0]

    def draw(self, screen):
        if self.mouseimage != None:
            screen.blit(self.mouseimage, (self.screenrect[0], self.screenrect[1]))

    def adjposscr(self, x=0, y=0):
        """Just a place holder"""

    def update(self):
        """Do any updating needed"""

def main():
    make_bkg()

    # The map defaults
    tilefile = "default.bmp"
    bgtag = "default.background"
    filename = None
    width = 992
    height = 992
    musicfile = None

    tilewidth = 32
    tileheight = 32

    # If a command line arg is passed:
    if len(sys.argv) > 7:
        if sys.argv[1] == "create":
            filename = sys.argv[2]
            tilefile = sys.argv[3]
            #tilewidth = string.atoi(sys.argv[4])
            #tileheight = string.atoi(sys.argv[5])
            width = string.atoi(sys.argv[4])
            height = string.atoi(sys.argv[5])
            bgtag = sys.argv[6]
            musicfile = sys.argv[7]

            # Width passed on the command line is in tiles, not pixels, convert
            width = width * tilewidth
            height = height * tileheight

    elif len(sys.argv) == 2:
        filename = sys.argv[1]
    else:
        print "Usage: \n"
        print "Create new: maptool create <filename> <tilefile> <number of tiles wide> <num tiles heigh> <bgimgtag> <musicfile>" 
        print "Load pre-existng: maptool <filename>" 
        sys.exit()

    # Load map 
    map1 = map_base(filename, bgtag, tilefile, mapsize=(width, height), viewrect=[ 0, 0, 640, 480 ])

    if map1.musicfile == None:
        map1.musicfile = musicfile

    print map1.musicfile

    # Initialize tile menu
    tilemenu = tilemenu_base(viewrect=[650, 10, 790, 590], wh=(32, 32))

    # Load the tile file that the map is using
    tilemenu.loadtiles(map1.bmpfile)

    # Load/Initialize character menu (Note, we are loading default char list, it can be specified in args as well)
    charmenu = charmenu_base(viewrect=[650, 10, 790, 590])

    # Initialize domenu
    domenu = domenu_base(viewrect=[10, 490, 640, 590], tileimage=tilemenu.tiles[0])

    # Initialize mouse
    mouse1 = mouse()

    # Initialize hud
    hud = hud_base("hud.bmp")

    # No need for a clock at this point, just let it run as fast as it will. 
    clock = pygame.time.Clock()

    # A flag to determine which menu (Currently tile and char) is active
    menuactive = 0

    # Whether or not shift is down
    shiftflag = 0
    
    # Whether or not ctrl is down
    ctrlflag = 0

    # Whether or not the del key is down
    delflag = 0
    
    # If time to quit, == 1
    quit = 0
    while not quit:
    
        #clock.tick(20)
        background.fill((255, 255, 255))
        make_bkg(" ")

        mouse1.screenrect = pygame.mouse.get_pos()

        for event in pygame.event.get():
            if event.type == QUIT:
                quit = 1
            elif event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    quit = 1
                if event.key == K_F1:
                    domenu.statustext = "Saving " + `map1.mapfile` + "..."
                    map1.savedata()
                if event.key == K_F5:
                    domenu.statustext = "Loading " + `map1.mapfile` + "..."
                    map1.loaddata()
                if event.key == K_LSHIFT or event.key == K_RSHIFT:
                    shiftflag = 1
                if event.key == K_LCTRL or event.key == K_RCTRL:
                    ctrlflag = 1
                if event.key == K_DELETE or event.key == K_x:
                    delflag = 1
                if event.key == K_1:
                    # Erase
                    domenu.addselected(-1, clear=1)
                if event.key == K_2:
                    # Invisible
                    domenu.addselected(-2, clear=1)
                if event.key == K_3:
                    # End of level
                    domenu.addselected(-3, clear=1)
                if event.key == K_4:
                    # NPC Ivisible (Invisible to player but not NPC)
                    domenu.addselected(-4, clear=1)
                if event.key == keyup:
                    if menuactive == 0:
                        tilemenu.scroll(value=-1)
                    elif menuactive == 1:
                        charmenu.scroll(value=-1)
                    pass
                if event.key == keydown:
                    if menuactive == 0:
                        tilemenu.scroll(value=1)
                    elif menuactive == 1:
                        charmenu.scroll(value=1)
                    pass
                if event.key == keyleft:
                    if menuactive == 1:
                        menuactive = 0
                    elif menuactive == 0:
                        menuactive = 1

                    pass 
                if event.key == keyright:
                    if menuactive == 1:
                        menuactive = 0
                    elif menuactive == 0:
                        menuactive = 1

                    pass 
                if event.key == keyjump:
                    # Create a seed for the random function
                    seed = mouse1.screenrect[0] + mouse1.screenrect[1] + clock.get_time()
                    # Switch out the selected tiles with a random set from domenu
                    map1.changetile(domenu, seed)
                    
                    # Clear draw list
                    map1.currentlist = []
                    pass 

                if map1.selattrib:
                    if event.key == K_p:
                        if map1.selattrib[0] == 1:
                            map1.selattrib[0] = 0
                        else:
                            map1.selattrib[0] = 1

                    if event.key == K_l:
                        if map1.selattrib[1] == 1:
                            map1.selattrib[1] = 0
                        else:
                            map1.selattrib[1] = 1

                    if event.key == K_t:
                        if map1.selattrib[2] == 1:
                            map1.selattrib[2] = 0
                        else:
                            map1.selattrib[2] = 1

                    if event.key == K_r:
                        if map1.selattrib[3] == 1:
                            map1.selattrib[3] = 0
                        else:
                            map1.selattrib[3] = 1

                    if event.key == K_b:
                        if map1.selattrib[4] == 1:
                            map1.selattrib[4] = 0
                        else:
                            map1.selattrib[4] = 1

                    if event.key == K_d:
                        if map1.selattrib[5] == 1:
                            map1.selattrib[5] = 0
                        else:
                            map1.selattrib[5] = 1

                    if event.key == K_s:
                        if map1.selattrib[6] == 1:
                            map1.selattrib[6] = 0
                        else:
                            map1.selattrib[6] = 1

                    # If the user presses "a", all tiles with the current tileid will be set to the same attributes
                    if event.key == K_a:
                        map1.changeallattrib(map1.maplist[map1.selected[0]], map1.selattrib)

                    map1.changeattrib(map1.selattrib)

            elif event.type == KEYUP:
                if event.key == keyup:
                    if menuactive == 0:
                        tilemenu.scroll(0)
                    elif menuactive == 1:
                        charmenu.scroll(0)
                    pass
                if event.key == keydown:
                    if menuactive == 0:
                        tilemenu.scroll(0)
                    elif menuactive == 1:
                        charmenu.scroll(0)
                    pass
                if event.key == K_LSHIFT or K_RSHIFT:
                    shiftflag = 0
                if event.key == K_RCTRL or K_LCTRL:
                    ctrlflag = 0
                if event.key == K_DELETE or K_x:
                    delflag = 0
                if event.key == keyleft:
                    pass
                if event.key == keyright:
                    pass
                if event.key == keyjump:
                    pass

            elif event.type == MOUSEBUTTONDOWN:
                mouse1.mousestate = pygame.mouse.get_pressed()
                mouse1.up = 0
                mouse1.down = 1

            elif event.type == MOUSEBUTTONUP:
                mouse1.mousestate = pygame.mouse.get_pressed()
                mouse1.up = 1
                mouse1.down = 0

        # if mouse left click
        if mouse1.mousestate[0]:
            
            if map1.getclick(mouse1):
                tile = map1.returntile(mouse1)

                # If the mouse charbuffer is full, i.e. a char is selected, process that instead of selecting a tile
                if mouse1.charbuffer != None:
                    # Add this char to the tile in question
                    map1.addchar(tile, charmenu, mouse1.charbuffer)

                    # Clear the character buffer, this is a little bit of a pain, but
                    # Prevents accidental inclusion of the char more than once.
                    mouse1.mouseimage = None
                    mouse1.charbuffer = None

                # If ctrl is being held down
                elif delflag:
                    # See if one of the chars is being clicked
                    for char in map1.charlist:
                        # If this char got the click
                        if char.getclick((mouse1.screenrect[0] + map1.viewport[0], mouse1.screenrect[1] + map1.viewport[1])):
                            map1.removechar(char)
                            break

                # If shift and ctrl are being held down
                elif shiftflag:
                    # If the mouse button is being held down
                    if mouse1.down:
                        # Add the selected tile to the list of selected tiles
                        map1.addselected(tile, rangelast=1)

                # If shift is being held down
                elif ctrlflag:
                   # If the mouse button is being held down
                   if mouse1.down:
                        # Add the selected tile to the list of selected tiles
                        map1.addselected(tile)
                    
                else:
                    # Clear currently selected list of tiles, and add current tile
                    map1.addselected(tile, clear=1)

                #domenu.tiletorep = map1.returntile(mouse1)
                #domenu.selattrib = map1.selectedattrib
            elif tilemenu.getclick(mouse1) and menuactive == 0:

                tile = tilemenu.returntile(mouse1)
                
                if shiftflag:
                    domenu.addselected(tile, tileimage=tilemenu.tiles[ tile ])
                else:
                    domenu.addselected(tile, tileimage=tilemenu.tiles[ tile ], clear=1)

            elif charmenu.getclick(mouse1) and menuactive == 1:
                char = charmenu.returntile(mouse1)

                # Copy the char image to mouse follow
                mouse1.mouseimage = charmenu.tiles[char]
                # Copy the character index to the mouse buffer
                mouse1.charbuffer = char

            elif domenu.getclick(mouse1):
                # Get new attributes from user
                newattributes = domenu.getattributes(map1.selattrib)
                # Assign new attributes to map tiles
                map1.selattrib = newattributes
                map1.changeattrib(newattributes)

        # Else if right click
        elif mouse1.mousestate[2]:

            if mouse1.charbuffer:
                mouse1.mouseimage = None
                mouse1.charbuffer = None
            else: 
                tile = map1.returntile(mouse1)
                map1.removeselected(tile)

        # Get status text for domenu
        domenu.statustext = map1.status
        domenu.mapinfotext = "Map position: " + `map1.viewport` + " - " + `len(map1.selected)` + " map tiles selected."
        
        # Figure out what the attributes for the selected map tile are
        domenu.parseattributes(map1.selattrib)

        # Run tile menu updates
        if menuactive == 0:
            tilemenu.update()
        elif menuactive == 1:
            charmenu.update()
       
        # Highlight tile under mouse
        mouse1.over = map1.returntile(mouse1)
        map1.highlighttile(mouse1.over, green=1)

        # If we have clicked the middle mouse button, start centering
        if mouse1.mousestate[1]:
            xhalf = screenwidth / 2
            yhalf = screenheight / 2

            if mouse1.screenrect[0] > xhalf:
                xspeed = (mouse1.screenrect[0] - xhalf) * 0.3
            elif mouse1.screenrect[0] < xhalf:
                xspeed = (xhalf - mouse1.screenrect[0]) * 0.3
            
            if mouse1.screenrect[1] > yhalf:
                yspeed = (mouse1.screenrect[1] - yhalf) * 0.3
            elif mouse1.screenrect[1] < yhalf:
                yspeed = (yhalf - mouse1.screenrect[1]) * 0.3

            xspeed = int(xspeed)
            yspeed = int(yspeed)

            if xspeed > yspeed:
                speed = xspeed
            else:
                speed = yspeed

            #print speed

            map1.softcenter(mouse1, speed)

        # Update the map info
        map1.update()
        
        # Make a list of tiles for map draw and coldet routines
        map1.makelist()

        # Draw plain background to screen
        screen.blit(background, (0, 0))

        # Draw each of the objects to the screen
        map1.draw(screen)

        if menuactive == 0:
            tilemenu.draw(screen)
        elif menuactive == 1:
            charmenu.draw(screen)

        domenu.draw(screen)
        hud.draw(screen)
        mouse1.draw(screen)
        
        pygame.display.flip()

# Start the main function running
main()
