"""game_menu.py

   Display the main menu system

   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 
"""


import pygame
from game_config import config

## 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 menu_item:
    """Menu items"""

    # The type is standard or st
    type = 'st'

    rect = []
    text = None
    image = None

    # This is the image to use for background
    imagename = None

    # This variable is set to 1 if this item is waiting for input
    waiting = 0

    # This is what level the item is bound to. If say, 1, clicking this item will take you to
    # menu level 1, a negative number indicates that this item is not bound to a menu level
    binding = -1

    font = pygame.font.Font(None, 36)

    def __init__(self, x1, y1, x2, y2, text, binding=-1):
        """Init item, takes rect and text"""
        self.image = pygame.Surface(( x2 - x1, y2 - y1))
        self.setupbackground(self.imagename)

        self.rect = [ x1, y1, x2, y2 ]

        self.changetext(text)

        self.binding = binding

    def getclick(self, (mousex, mousey)):
        """Check whether or not this item got a mouse click"""

        if mousex < self.rect[0]:
            return(0)
        elif mousex > self.rect[2]:
            return(0)
        elif mousey < self.rect[1]:
            return(0)
        elif mousey > self.rect[3]:
            return(0)
        else:
            return(1)

    def setupbackground(self, imgname=None):
        """Load a background image for this item"""

        if imgname:
            self.image = myimg.loadimage(imgname, colorkey=-1)
        else:
            self.image = self.image.convert()
            self.image.fill((0, 0, 0))

    def getinput(self, key):
        pass

    def changetext(self, newtext):
        """Change the text displayed on this item"""
        self.setupbackground(self.imagename)
        self.text = self.font.render(newtext, 1, (210, 210, 210))

        textpos = self.text.get_rect()
        textpos.centerx = self.image.get_rect().centerx
        
        self.image.blit(self.text, textpos)

    def draw(self, screen):
        screen.blit(self.image, (self.rect[0], self.rect[1]))

class menu_item_keyvar(menu_item):
    """A menu item that takes a keyboard single key input for key mapping purposes"""

    # The type is keyvar or kv
    type = 'kv'

    # Keyname is what this key is called in the keybindings
    keyname = None
    keyvalue = None

    def __init__(self, x1, y1, x2, y2, text, binding=-1, key=None, keyname=None):
        """Init item, takes rect and text"""
        self.image = pygame.Surface(( x2 - x1, y2 - y1))
        self.setupbackground(self.imagename)

        self.rect = [ x1, y1, x2, y2 ]

        self.changetext(text)

        self.binding = binding

        self.keyvalue = key
        self.keyname = keyname

    def getinput(self, key):
        """Get input from the user"""

        # Change the item in the config
        config.changekey(self.keyname, key)

        self.keyvalue = key
        self.waiting = 0

        keytxt = pygame.key.name(key)

        newtxt = self.keyname + " - " + keytxt

        self.changetext(newtxt)

class menu_item_slider(menu_item):
    """A slider control"""

    # The type is keyvar or kv
    type = 'vol'

    sliderimg = None

    sliderx = 0
    slidery = 0

    sliderwidth = 4

    def __init__(self, x1, y1, x2, y2, text, binding=-1, sliderimg=None, type="mvol"):
        """Init item, takes rect and text"""

        self.type = type

        self.image = pygame.Surface(( x2 - x1, y2 - y1))
        self.setupbackground(self.imagename)

        self.sliderimg = pygame.Surface(( self.sliderwidth, y2 - y1))
        self.setupsliderknob(sliderimg)

        self.rect = [ x1, y1, x2, y2 ]

        # Determine at what percentage point the current volume
        if type == "mvol":
            loc = config.musicvol * (x2 - x1)
            loc = x1 + loc
        elif type == "svol":
            loc = config.soundvol * (x2 - x1)
            loc = x1 + loc

        # Quick check to make sure we stay in bounds of the menu
        if (loc + self.sliderwidth) > self.rect[2]:
            loc = x2 - self.sliderwidth

        self.sliderx = loc
        self.slidery = y1

        self.changetext(text)

        self.binding = binding

    def getclick(self, (mousex, mousey)):
        """Check whether or not this item got a mouse click"""

        if mousex < self.rect[0]:
            return(0)
        elif mousex > self.rect[2]:
            return(0)
        elif mousey < self.rect[1]:
            return(0)
        elif mousey > self.rect[3]:
            return(0)
        else:

            width = self.rect[2] - self.rect[0]

            where = mousex - self.rect[0]

            # Get the percentage of click
            percent = float(where) / float(width)

            # Debug
            #print width, where, percent

            if self.type == "mvol":
                # Set the configuration music volume
                config.musicvol = percent
            elif self.type == "svol":
                # Set the configuration sfx volume
                config.soundvol = percent

            if (mousex + self.sliderwidth) > self.rect[2]:
                self.sliderx = self.rect[2] - self.sliderwidth
            else:
                self.sliderx = mousex

            self.slidery = self.rect[1]

            return(1)

    def setupsliderknob(self, imgname=None):
        """Load a slider image for this item"""

        if imgname:
            self.sliderimg = myimg.loadimage(imgname, colorkey=-1)
        else:
            self.sliderimg = self.sliderimg.convert()
            self.sliderimg.fill((255, 255, 255))

    def draw(self, screen):
        screen.blit(self.image, (self.rect[0], self.rect[1]))
        screen.blit(self.sliderimg, (self.sliderx, self.slidery))

class menu_base:
    """The menu"""

    # The pre-set levels
    keymaplevel = 2
    soundlevel = 3

    width = 0
    height = 0
    rect = []
    items = []
    background = None
    menulevel = 0

    # This flag is set if an item is waiting for input
    waiting = 0

    # Default height for menu items
    itemheight = 32

    def __init__(self, x1, y1, x2, y2, background=None, levels=0):
        """Initialize the main menu object, levels indicates how many total levels this menu will have"""
        self.rect = [ x1, y1, x2, y2 ]

        self.width = x2 - x1
        self.height = y2 - y1
       
        # Load a background image if one is specified, otherwise make a black background
        if background != None:
            self.background = myimg.loadimage(background, colorkey=-1)
        else:
            self.background = pygame.Surface((self.width, self.height))
            self.background = self.background.convert()
            self.background.fill((0, 0, 0))

        # Setup the number of levels
        for i in range(levels):
            self.items.append([])

        # Level to display keymap data on Note: level starts at 0, so 2 is really level 3
        level = self.keymaplevel

        pad = 0
        i = 0

        # Add all of the keys from config into the level defined by keymaplevel
        for (keyname, keyval) in config.keymap:
            x1 = self.rect[0]
            y1 = self.rect[1] + pad
            x2 = self.rect[2]
            y2 = y1 + self.itemheight

            keytxt = pygame.key.name(keyval)

            text = keyname + " - " + keytxt

            self.items[level].append(menu_item_keyvar(x1, y1, x2, y2, text, binding=-1, keyname=keyname, key=keyval))

            pad += self.itemheight

        # Finally, add a back button
        x1 = self.rect[0]
        y1 = self.rect[1] + pad + self.itemheight
        x2 = self.rect[2]
        y2 = y1 + self.itemheight
        self.items[level].append(menu_item(x1, y1, x2, y2, "Back", binding=1))

        # Reset pad
        pad = 0

        # Add the volume controls
        x1 = self.rect[0]
        y1 = self.rect[1]
        x2 = self.rect[2]
        y2 = y1 + self.itemheight
        self.items[self.soundlevel].append(menu_item(x1, y1, x2, y2, "Music Vol:", binding=-1))

        pad += self.itemheight

        x1 = self.rect[0]
        y1 = self.rect[1] + pad
        x2 = self.rect[2]
        y2 = y1 + self.itemheight
        self.items[self.soundlevel].append(menu_item_slider(x1, y1, x2, y2, "<<<< >>>>", binding=-1, type="mvol"))

        pad += self.itemheight

        x1 = self.rect[0]
        y1 = self.rect[1] + pad
        x2 = self.rect[2]
        y2 = y1 + self.itemheight
        self.items[self.soundlevel].append(menu_item(x1, y1, x2, y2, "Sound Vol:", binding=-1))

        pad += self.itemheight

        x1 = self.rect[0]
        y1 = self.rect[1] + pad
        x2 = self.rect[2]
        y2 = y1 + self.itemheight
        self.items[self.soundlevel].append(menu_item_slider(x1, y1, x2, y2, "<<<< >>>>", binding=-1, type="svol"))

        pad += self.itemheight

        x1 = self.rect[0]
        y1 = self.rect[1] + pad + self.itemheight
        x2 = self.rect[2]
        y2 = y1 + self.itemheight
        self.items[self.soundlevel].append(menu_item(x1, y1, x2, y2, "Back", binding=1))

    def additem(self, level, (y1, height), text, binding):
        """Add an item to the item list at level with binding"""

        x1 = self.rect[0]
        x2 = self.rect[2]
        y2 = y1 + height

        self.items[level].append(menu_item(x1, y1, x2, y2, text, binding))

    def getinput(self, key):
        # Debug
        #print key

        # We're no longer waiting for input
        self.waiting = 0

        # Loop through all items looking for one that's waiting for input
        for item in self.items[self.keymaplevel]:
            # Once we find it, assign the key value to it and unset item.waiting
            if item.waiting:
                item.getinput(key)

    def getclick(self, (mousex, mousey)):
        """Find out whether one of the items got clicked"""

        for item in self.items[self.menulevel]:
            gotclick = item.getclick((mousex, mousey))

            if gotclick:
                if item.type == 'st':
                    if item.binding >= 0:
                        self.menulevel = item.binding

                # If the item type is keyvalue, set the waiting flag to true
                # This means that on the next input, this item will get the keypress
                # Only keyvar items have the waiting value
                elif item.type == 'kv':
                    item.changetext('Press New Key')
                    item.waiting = 1
                    self.waiting = 1

        return(self.menulevel)

    def draw(self, screen):

        screen.blit(self.background, (self.rect[0], self.rect[1]))

        # if we had one of the special values, reset to 0
        if self.menulevel > 800:
            self.menulevel = 0

        for item in self.items[self.menulevel]:
            item.draw(screen)


