# -*- coding: latin-1 -*-
# Balazar
# Copyright (C) 2003-2005 Jean-Baptiste LAMY
#
# This program 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.
#
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

import os, os.path, time, random
import tofu
import soya, soya.opengl as soyaopengl, soya.sdlconst as sdlconst, soya.tofu4soya, soya._soya, soya.widget as widget
import balazar, balazar.sound, balazar.base as base, balazar.globdef as globdef, balazar.controller as controller
from balazar.character import _P, _V

def init():
  if not soya.inited:
    soya.init(title = "Balazar", width = globdef.SCREEN_WIDTH, height = globdef.SCREEN_HEIGHT, fullscreen = globdef.FULLSCREEN)
    soya.set_quality(globdef.QUALITY)
    
    SHADER_DEFAULT_MATERIAL = soya.Material.get("shader")
    SHADER_DEFAULT_MATERIAL.filename = "__SHADER_DEFAULT_MATERIAL__"
    soya._soya._set_shader_default_material(SHADER_DEFAULT_MATERIAL)
    
    widget.big_font     = widget.default_font
    widget.default_font = soya.Font(os.path.join(soya.DATADIR, "FreeSans.ttf"), 18, 15)
    
  # Display the splash screen
  soya.set_root_widget(widget.Image(None, soya.Material.get("splash"), resize_style = ("maximize",)))
  soya.render()
  soya.root_widget = None
  

class Idler(soya.tofu4soya.Idler):
  def __init__(self, scene = None):
    soya.tofu4soya.Idler.__init__(self, scene)
    self.big_round_count = 0
    
    self.min_frame_duration = globdef.MIN_FRAME_DURATION
    
  def begin_round(self):
    if globdef.WAIT_FOR_SOUND: time.sleep(0.00001)
    
    soya.tofu4soya.Idler.begin_round(self)
    
    if self.big_round_count == 0:
      self.big_round_count = 15
      for scene in self.scenes:
        scene.big_round()
    else: self.big_round_count -= 1
    
    
class Scene(soya.World):
  def __init__(self):
    soya.World.__init__(self)
    self.camera = None
    
    from balazar.weather import WeatherAtmosphere
    
    self.atmosphere = WeatherAtmosphere(self)
    
  def advance_time(self, proportion):
    soya.World.advance_time(self, proportion)
    self.atmosphere.advance_time(proportion)
    
  def begin_round(self):
    soya.World.begin_round(self)
    self.atmosphere.begin_round()
    
  def big_round(self):
    self.atmosphere.big_round()
    
    for child in self.children:
      if hasattr(child, "big_round"): child.big_round()
      
      
def check_path(d):
  if not os.path.exists(d): os.mkdir(d)
  
def set_path_current(player_filename, enable):
  check_path(globdef.SAVED_GAME_DIR)
  d = os.path.join(globdef.SAVED_GAME_DIR, player_filename)
  check_path(d)
  check_path(os.path.join(d, "players"))
  check_path(os.path.join(d, "levels"))
  
  d = os.path.join(globdef.SAVED_GAME_DIR, player_filename)
  if enable: tofu.path.insert(0, d)
  else:      tofu.path.remove(d)
    
    
def start_single(login, password = ""):
  globdef.mode = "--single"
  scene = Scene()
  Idler(scene)
  init()
  
  try:
    import tofu.single
    set_path_current(login, 1)
    r = tofu.single.serve_forever(login = login, password = password)
  finally:
    set_path_current(login, 0)
    
  if r == "paused":
    while 1:
      time.sleep(0.1)
      for event in soya.process_event():
        if (event[0] == sdlconst.KEYDOWN) or (event[0] == sdlconst.JOYBUTTONDOWN):
          break
      else: continue
      break
    return start_single(login, password)

  balazar.sound.end_music()
  return r
  
  
def start_server():
  globdef.mode = "--server"
  scene = Scene()
  Idler(scene)
  if globdef.SERVER_VIEW:
    init()
    soya.set_root_widget(ServerView(scene))
    
  try:
    import tofu.server
    set_path_current("_server", 1)
    r = tofu.server.serve_forever()
  finally:
    set_path_current("_server", 0)
    
  return r
  
  
def start_client(hostname, login, password = "", port = 6900):
  globdef.mode = "--client"
  scene = Scene()
  Idler(scene)
  init()
  
  import tofu.client
  r = tofu.client.serve_forever(hostname, login = login, password = password)
  if r == "paused":
    while 1:
      time.sleep(0.1)
      for event in soya.process_event():
        if (event[0] == sdlconst.KEYDOWN) or (event[0] == sdlconst.JOYBUTTONDOWN):
          break
      else: continue
      break
    return start_client(hostname, login, password = "", port = 6900)
  
  balazar.sound.end_music()
  return r
  

class GameInterface(soya.tofu4soya.GameInterface):
  def __init__(self, login, password = ""):
    soya.tofu4soya.GameInterface.__init__(self)
    
    self.login    = login
    self.password = password

    self.hero = None
    self.traveling = None
    self.camera = soya.IDLER.scenes[0].camera = soya.TravelingCamera(soya.IDLER.scenes[0])
    self.camera.back = 100.0
    self.camera.speed = 0.4
    #self.camera.add_traveling(soya.FixTraveling(soya.Point(), soya.Vector(None, 0.0, 0.0, -1.0)))
    self.camera.add_traveling(soya.FixTraveling(self.camera, soya.Vector(self.camera, 0.0, 0.0, -1.0)))
    balazar.sound.init(self.camera)
    self.root_widget = widget.Group()
    self.root_widget.add(self.camera)
    soya.set_root_widget(self.root_widget)
    soya.widget.FPSLabel(self.root_widget)

    self.life_bar           = LifeBar  (self.root_widget)
    #self.map_viewer         = MapViewer(self.root_widget)
    self.active_widgets     = []
    self.current_discussion = None
    self.current_country    = None
    
  def network_error(self, reason):
    soya.IDLER.stop(reason)
    
  def ready(self, notifier):
    soya.tofu4soya.GameInterface.ready(self, notifier)
    
    self.notifier.login_player(self.login, self.password)
    
  def close_all_widgets(self):
    for w in self.active_widgets:
      w.destroy()
    

class ServerView(soya.TravelingCamera):
  def __init__(self, parent = None):
    soya.TravelingCamera.__init__(self, parent)
    
    self.back = 100.0
    self.speed = 0.4
    
    self.set_mobile(None)
    
  def begin_round(self):
    soya.TravelingCamera.begin_round(self)
    
    for event in soya.process_event():
      if event[0] == sdlconst.KEYDOWN:
        if event[1] == sdlconst.K_TAB:
          mobiles = [i for i in self.parent.recursive() if isinstance(i, balazar.character.Character)]
          if mobiles:
            if self.mobile in mobiles: i = mobiles.index(self.mobile)
            else:                      i = -1
            if i + 1 >= len(mobiles): self.set_mobile(None)
            else:                     self.set_mobile(mobiles[i + 1])
            
  def set_mobile(self, mobile):
    self.mobile = mobile
    if mobile: self.add_traveling(soya.ThirdPersonTraveling(mobile, soya.Vector(None, 0.0, 0.0, 2.0)))
    else:      self.add_traveling(soya.FixTraveling(soya.Point(), soya.Vector(None, 0.0, 0.0, -1.0)))
    
      
    
class ActiveWidget:
  def __init__(self):
    tofu.GAME_INTERFACE.active_widgets.insert(0, self)
    
  def key_down(self, key): """Returns 1 if the event has been consumed"""
  
  def destroy(self):
    try: self.master.remove(self)
    except: pass
    try: tofu.GAME_INTERFACE.active_widgets.remove(self)
    except: pass

class FocusableWidget(ActiveWidget):
  def __init__(self):
    self.focus = 0
    ActiveWidget.__init__(self)

  def set_focus(self, focus, play_sound = 1):
    self.focus = focus
    if focus and play_sound: balazar.sound.play("menu2.wav")
    
  def key_down(self, key):
    if  (key == controller.CONTROL_QUIT  ) and self.focus: self.set_focus(0)
    elif(key == controller.CONTROL_JUMP  ) and self.focus: self.set_focus(0)
    elif(key == controller.CONTROL_STRIKE) and self.focus: self.set_focus(0)
    elif(key == controller.CONTROL_ITEM  ) and self.focus: self.set_focus(0)
    elif key == controller.CONTROL_MENU:
      focusable = [widget for widget in tofu.GAME_INTERFACE.active_widgets if isinstance(widget, FocusableWidget)]
      if self is focusable[0]:
        for widget in focusable:
          if widget.focus: break
        else:
          self.set_focus(1)
          return 1
      else:
        preceding = focusable[focusable.index(self) - 1]
        if preceding.focus:
          preceding.set_focus(0)
          self     .set_focus(1)
          return 1
      if (self is focusable[-1]) and self.focus:
        self.set_focus(0)
        # Do NOT return 1, => open inventory


class Bubble(widget.Widget, FocusableWidget):
  def __init__(self, master = None, character = None, inner_widget = None):
    for w in tofu.GAME_INTERFACE.active_widgets:
      if isinstance(w, Bubble): w.destroy()
      
    FocusableWidget.__init__(self)
    widget.Widget.__init__(self, master)
    
    self.character      = character
    self.widget         = inner_widget
    inner_widget.master = self
    inner_widget.resize(0, 0, 500, 600)
    
    self.width  = int(inner_widget.width  + 28)
    self.height = int(inner_widget.height + 20)
    
    self.top        = 0
    self.position   = soya.Point()
    self.focus      = 0
    self.visible    = 1
    
    tofu.GAME_INTERFACE.current_discussion = self
    
  def destroy(self):
    if isinstance(self.widget, DiscussionWidget):
      if isinstance(self.widget.discussion, AutoDiscussion):
        self.widget.discussion.hero.doer.do_action(balazar.character.DiscussionAction(balazar.character.ACTION_END_DISCUSSING, self.widget.discussion.character))
        
    tofu.GAME_INTERFACE.current_discussion = None
    
    try: tofu.GAME_INTERFACE.active_widgets.remove(self.widget)
    except: pass
    
    FocusableWidget.destroy(self)
    
  def set_focus(self, focus, play_sound = 1):
    FocusableWidget.set_focus(self, focus, play_sound)
    self.widget.set_focus(focus)
  
  def check(self):
    return self.widget.check()
  
  def resize(self, parent_left, parent_top, parent_width, parent_height):
    pass
    
  def mouse_moved(self,         x, y): return self.widget.mouse_moved(        x, y) or ((self.left <= x <= self.left + self.width) and (self.top <= y <= self.top + self.height))
  def mouse_down (self, button, x, y): return self.widget.mouse_down (button, x, y) or self.mouse_moved(x, y)
  def mouse_up   (self, button, x, y): return self.widget.mouse_up   (button, x, y) or self.mouse_moved(x, y)
  def key_down   (self, key         ):
    if self.focus:
      return self.widget.key_down(key) or FocusableWidget.key_down(self, key)
    return FocusableWidget.key_down(self, key)
  
  def widget_begin_round (self            ): self.widget.widget_begin_round()
  def widget_advance_time(self, proportion): self.widget.widget_advance_time(proportion)
  def widget_end_round   (self            ): self.widget.widget_end_round()
  
  def render(self):
    if not self.visible: return
    
    self.position.__init__(self.character, 0.0, 2.6, 0.0)
    self.position.convert_to(tofu.GAME_INTERFACE.camera)
    if self.position.z > 0.0: return
    self.position.__init__(self.character, 0.0, 2.6, 0.0)
    x, y = tofu.GAME_INTERFACE.camera.coord3d_to_2d(self.position)
    
    #if x < tofu.GAME_INTERFACE.camera.width / 2 - 30: self.left = 0
    #else:                                    self.left = tofu.GAME_INTERFACE.camera.width - self.width
    self.left = tofu.GAME_INTERFACE.camera.width - self.width
    self.top = 0
    content_left = self.left + 14
    content_top  = self.top  + 5
    
    soyaopengl.glPushMatrix()
    soyaopengl.glTranslatef(self.left, self.top, 0.0)
    
    soya.DEFAULT_MATERIAL.activate()
    soyaopengl.glEnable(soyaopengl.GL_BLEND)
    if self.focus: soyaopengl.glColor4f(1.0, 1.0, 1.0, 1.0)
    else:          soyaopengl.glColor4f(1.0, 1.0, 1.0, 0.5)
    soyaopengl.glBegin(soyaopengl.GL_POLYGON)
    soyaopengl.glVertex2i(0, 0)
    if self.left == 0:
      soyaopengl.glVertex2i(0              , self.height)
      soyaopengl.glVertex2i(self.width - 15, self.height)
      soyaopengl.glVertex2i(self.width - 5 , self.height -  5)
      soyaopengl.glVertex2i(self.width     , self.height - 15)
      
    else:
      soyaopengl.glVertex2i(0         , self.height - 15)
      soyaopengl.glVertex2i(5         , self.height -  5)
      soyaopengl.glVertex2i(15        , self.height)
      soyaopengl.glVertex2i(self.width, self.height)
      
    soyaopengl.glVertex2i(self.width, 0)
    soyaopengl.glEnd()
    soyaopengl.glBegin(soyaopengl.GL_TRIANGLES)
    soyaopengl.glVertex2i(int(self.width * 0.4), self.height)
    soyaopengl.glVertex2i(int(self.width * 0.3), self.height)
    soyaopengl.glColor4f(1.0, 1.0, 1.0, 0.1)
    soyaopengl.glVertex2i(int(round(x - self.left)), int(round(max(y, self.height + 20) - self.top)))
    soyaopengl.glEnd()
    soyaopengl.glDisable(soyaopengl.GL_BLEND)
    
    soyaopengl.glTranslatef(14.0, 5.0, 0.0)
    self.widget.render()
    
    soyaopengl.glPopMatrix()
  




VOICE = None
class Discussion(object):
  def __init__(self, character, reply, text = u"", condition = 1, action = None, check = None, source = None, voice = None, choices = ()):
    self.character   = character
    self.reply       = reply
    self.text        = text
    self.condition   = condition
    self.action      = action
    self.check       = check
    self.source      = source or character
    self.voice       = voice
    
    if not callable(choices): self.set_choices(choices)
    else:                     self._choices = choices
    
  def activate(self, focus = 0):
    if self.action: self.action()
    if self.text:
      global VOICE
      if VOICE: VOICE.stop()
      try: VOICE = sound.play(self.voice or (u"voice_%s.ogg" % " ".join(self.text.split()[:4])).encode("latin"))
      except: pass # No voice (for this discussion, or at all)
      
      discussion_widget = Bubble(soya.root_widget, self.character or tofu.GAME_INTERFACE.hero, DiscussionWidget(self))
      
      if focus:
        discussion_widget.set_focus(1, 0)
        if discussion_widget.widget.choices: discussion_widget.widget.selection = discussion_widget.widget.choices[0][0]
        
  def is_valid(self):
    if callable(self.condition): return self.condition()
    return self.condition
  
  def set_choices(self, choices):
    self._choices = []
    for choice in choices:
      if choice.is_valid():
        if self._choices and (self._choices[-1].reply == choice.reply): # Same text => replace
          self._choices[-1] = choice
        else:
          self._choices.append(choice)
          
    if self.text and not self._choices:
      self.set_choices([Discussion(self.character, _("Ok"))])
      
  def get_choices(self):
    if callable(self._choices): self.set_choices(self._choices())
    return self._choices
  choices = property(get_choices)
  
  

class AutoDiscussion(object):
  def __init__(self, hero, character, reply_key, text_key, check = None, source = None, voice = None):
    self.hero        = hero
    self.character   = character
    self.reply_key   = reply_key
    self.reply       = _(reply_key)
    self.text_key    = text_key
    self.text        = _(text_key)
    self.check       = check
    self.source      = source or character
    self.voice       = voice
    self._choices    = None
    
  def activate(self, focus = 0):
    if "_combat_" in self.text_key:
      self.hero.doer.do_action(balazar.character.DiscussionAction(balazar.character.ACTION_DISCUSSION, self.character, "combat"))
      
    action = getattr(self.character, "discussion_action_%s" % self.text_key, None)
    if action:
      #action(self.hero)
      self.hero.doer.do_action(balazar.character.DiscussionAction(balazar.character.ACTION_DISCUSSION, self.character, self.text_key))
      
    if self.text:
      global VOICE
      if VOICE: VOICE.stop()
      try: VOICE = sound.play(self.voice or (u"voice_%s.ogg" % " ".join(self.text.split()[:4])).encode("latin"))
      except: pass # No voice (for this discussion, or at all)
      
      discussion_widget = Bubble(soya.root_widget, self.character or tofu.GAME_INTERFACE.hero, DiscussionWidget(self))
      
      if focus:
        discussion_widget.set_focus(1, 0)
        if discussion_widget.widget.choices: discussion_widget.widget.selection = discussion_widget.widget.choices[0][0]
        
  def is_valid(self):
    is_valid = getattr(self.character, "discussion_is_valid_%s" % self.text_key, None)
    if is_valid: return is_valid(self.hero)
    return 1
  
  def get_choices(self):
    if not self._choices:
      self._choices = []
      nb = len(self.text_key)
      
      choice2text = {}
      for key in balazar.globdef.translator._catalog.keys():
        if key.startswith(self.text_key):
          nb_ = key[nb:].count("_")
          if   nb_ == 1:
            choice_key = key
            if not choice2text.has_key(choice_key):
              choice2text[choice_key] = []
              
          elif nb_ == 2:
            choice_key = key[:key.find("_", nb + 1)]
            if not choice2text.has_key(choice_key):
              choice2text[choice_key] = []
              
            text_key = key
            choice2text[choice_key].append(text_key)
            
      choice_keys = choice2text.keys()
      choice_keys.sort()
      for choice_key in choice_keys:
        text_keys = choice2text[choice_key]
        if not  text_keys: text_keys = [u""]
        else:
          if u"random" in text_keys[0][text_keys[0].rfind("_"):]:
            text_keys = [random.choice(text_keys)] # XXX multiplayer ???
          else: text_keys.sort()
        for text_key in text_keys:
          choice = AutoDiscussion(self.hero, self.character, choice_key, text_key, self.check, self.source)
          if choice.is_valid():
            if self._choices and (self._choices[-1].reply == choice.reply): # Same text => replace
              self._choices[-1] = choice
            else:
              self._choices.append(choice)
              
      if self.text and not self._choices:
        self._choices.append(Discussion(self.character, _("Ok")))
        
    return self._choices
  choices = property(get_choices)
  
  

def StartDiscussion(hero):
  return Discussion(hero, u"", _(u"__welcome__"),
                    choices = [
    Help(hero, _(u"Aide (ENTRÉE ou le BOUTON 3 du joypad)")),
    Discussion(hero, _(u"Je sais déjà jouer, merci !")),
    ])

def Help(hero, reply = u""):
  return Discussion(hero, reply,
                    _(u"Utilise les touches HAUT BAS GAUCHE DROITE ou la MANETTE du \
joypad pour te déplacer"), choices = [
    Discussion(hero,
               _(u"Suite (ENTRÉE ou le BOUTON 3 du joypad)"),
               _(u"Utilise la touche SHIFT ou le BOUTON 1 du joypad pour sauter. Appuie \
sur ENTRÉE ou le BOUTON 3 du joypad pour revenir à l'aide, puis en BAS pour \
sélectionner 'Suite', puis ENTRÉE ou le BOUTON 3 pour valider."), choices = [
      Discussion(hero,
                 _(u"Suite"),
                 _(u"Appuis sur la touche CONTRÔLE ou le BOUTON 2 du joypad pour te \
mettre en garde. Relâche le bouton pour frapper."), choices = [
        Discussion(hero,
                   _(u"Suite"),
                   _(u"Utilise les touches HAUT BAS GAUCHE DROITE ou la MANETTE du \
joypad pour te déplacer à l'intérieur des fenêtres. Utilise la touche ENTRÉE ou le \
BOUTON 3 du joypad pour valider, changer de fenêtre ou faire apparaître l'inventaire."), choices = lambda : [
          Help(hero, _(u"Reprendre l'aide au début")),
          Discussion(hero, _(u"Fin de l'aide")),
          ]),
        ]),
      ]),
    ])

def QuitMenu(hero):
  return Discussion(hero, u"", _(u"__game_name__"),
                    choices = [
    Discussion(hero, _(u"Continuer"), ),
    Discussion(hero, _(u"Quitter et enregistrer"), action = lambda : tofu.GAME_INTERFACE.end_game()),
    Discussion(hero, _(u"Quitter sans enregistrer (suicide)"),
               action = lambda : (hero.doer.do_action(balazar.character.Action(balazar.character.ACTION_KILLED)), hero.doer.do_action(balazar.character.Action(balazar.character.ACTION_KILLED)), hero.doer.do_action(balazar.character.Action(balazar.character.ACTION_KILLED)))),
    ])


class DiscussionScript(soya.CoordSyst, base.Discutable):
  def __init__(self, parent = None, discussion = None, radius = 5.0):
    soya.CoordSyst.__init__(self, parent)
    self.discussion        = discussion
    self.discussion_radius = radius
    if not self.discussion.source: self.discussion.source = self
    
  def start_discussion(self, hero):
    from balazar.controler  import GrabItem
    if self.discussion.is_valid(): self.discussion.activate()


class DiscussionWidget(widget.Label):
  def __init__(self, discussion):
    widget.Label.__init__(self)
    
    self.discussion = discussion
    self.selection  = None

  def set_focus(self, focus):
    if not focus: self.selection = None
    
  def resize(self, parent_left, parent_top, parent_width, parent_height):
    self.left = parent_left
    self.top  = parent_top
    
    self.width, self.text_height, self.text = self.font.wordwrap(self.discussion.text, parent_width)
    
    self.height  = self.text_height
    self.choices = []
    if self.discussion.choices:
      self.height += 10
      for choice in self.discussion.choices:
        width, height, text = self.font.wordwrap(choice.reply, 500)
        self.font.create_glyphs(text)
        self.choices.append((choice, height, text))
        if width > self.width: self.width = width
        self.height += height
    
  def check(self):
    if self.discussion.check and not self.discussion.check(): return 0
    if tofu.GAME_INTERFACE.hero.distance_to(self.discussion.source) > self.discussion.source.discussion_radius: return 0
    return 1
    
  def key_down(self, key):
    if  (key == controller.CONTROL_QUIT  ): self.selection = None; self._changed = -2
    elif(key == controller.CONTROL_JUMP  ): self.selection = None; self._changed = -2
    elif(key == controller.CONTROL_STRIKE): self.selection = None; self._changed = -2
    elif(key == controller.CONTROL_ITEM  ): self.selection = None; self._changed = -2
    elif(key == controller.CONTROL_UP    ) and self.choices and ((not self.selection) or (len(self.choices) > 1)):
      if self.selection: self.selection = self.choices[self.discussion.choices.index(self.selection) - 1][0]
      else:              self.selection = self.choices[-1][0]
      self._changed = -2
      return 1
    elif(key == controller.CONTROL_DOWN) and self.choices and ((not self.selection) or (len(self.choices) > 1)):
      if self.selection: self.selection = self.choices[(self.discussion.choices.index(self.selection) + 1) % len(self.discussion.choices)][0]
      else:              self.selection = self.choices[ 0][0]
      self._changed = -2
      return 1
    elif(key == controller.CONTROL_MENU) and self.selection:
      self.choose(self.selection)
      return 1
    
  def choose(self, choice):
    balazar.sound.play("menu1.wav")
    self.master.destroy()
    choice.activate(1)
    
  def build_display_list(self):
    soyaopengl.glColor4f(0.0, 0.0, 0.0, 1.0)
    self._font.draw(self.text, self.left, self.top, 0)
    
    y = self.top + self.text_height + 10
    for choice, height, text in self.choices:
      if choice is self.selection: soyaopengl.glColor4f(0.0, 0.0, 1.0, 1.0)
      else:                        soyaopengl.glColor4f(0.5, 0.5, 0.5, 1.0)
      self._font.draw(text, self.left, y, 0)
      y += height
    

# class ActiveLabel(widget.Label, FocusableWidget):
#   def __init__(self, text):
#     FocusableWidget.__init__(self)
#     widget.Label.__init__(self, None, text, color = (0.0, 0.0, 1.0, 1.0))

#   def check(self): return 1
  
#   def set_focus(self, focus, play_sound = 1):
#     FocusableWidget.set_focus(self, focus, play_sound = 1)
#     if focus: self.color = (0.0, 0.0, 1.0, 1.0)
#     else:     self.color = (0.5, 0.5, 0.5, 1.0)
    
#   def key_down(self, key):
#     if key == controller.CONTROL_QUIT:
#       self.destroy()
#       return 1
    
#   def destroy(self):
#     balazar.sound.play("menu1.wav")
#     self.master.destroy()
    
    

class CameraTraveling: pass



class LifeBar(widget.Widget):
  def __init__(self, master = None):
    widget.Widget.__init__(self, master)
    
    self.left   =   5.0
    self.top    =   5.0
    self.width  =  70.0
    self.height = 300.0
    self._id1    = soyaopengl.glGenList()
    self._id2    = soyaopengl.glGenList()
    
    self.material = soya.Material.get("life")
    
  def __del__(self):
    soyaopengl.glDeleteList(self._id1)
    soyaopengl.glDeleteList(self._id2)
    
  def render(self):
    soya.DEFAULT_MATERIAL.activate()
    soyaopengl.glCallList(self._id1)
    
    self.material.activate()
    soyaopengl.glCallList(self._id2)
    
  def set_life(self, life):
    soyaopengl.glNewList(self._id1, soyaopengl.GL_COMPILE)
    soyaopengl.glEnable(soyaopengl.GL_BLEND)
    
    soyaopengl.glBegin(soyaopengl.GL_QUADS)
    soyaopengl.glColor4f(0.5, 0.0, 0.8, 0.7)

    top = self.top + 47.0 + (1.0 - life) * (self.height - 47.0)
    soyaopengl.glVertex2f(self.left              + 4.0, self.top + self.height - 20.0)
    soyaopengl.glVertex2f(self.left + self.width - 4.0, self.top + self.height - 20.0)
    soyaopengl.glVertex2f(self.left + self.width - 4.0, top)
    soyaopengl.glVertex2f(self.left              + 4.0, top)
    soyaopengl.glEnd()
    soyaopengl.glEndList()
    
    soyaopengl.glNewList(self._id2, soyaopengl.GL_COMPILE)
    soyaopengl.glBegin(soyaopengl.GL_QUADS)
    soyaopengl.glColor4f(1.0, 1.0, 1.0, 1.0)
    
    soyaopengl.glTexCoord2f(0.0, 1.0); soyaopengl.glVertex2f(self.left             , self.top + self.height)
    soyaopengl.glTexCoord2f(1.0, 1.0); soyaopengl.glVertex2f(self.left + self.width, self.top + self.height)
    soyaopengl.glTexCoord2f(1.0, 0.0); soyaopengl.glVertex2f(self.left + self.width, self.top)
    soyaopengl.glTexCoord2f(0.0, 0.0); soyaopengl.glVertex2f(self.left             , self.top)
    soyaopengl.glEnd()
    soyaopengl.glDisable(soyaopengl.GL_BLEND)
    soyaopengl.glEndList()
    
    
SIZE_2_TEX = {
  1 : 1.0  ,
  2 : 1.0  ,
  3 : 0.75 ,
  4 : 1.0  ,
  5 : 0.625,
  6 : 0.75 ,
  7 : 0.875,
  8 : 1.0  ,
  }

class MapViewer(widget.Widget, FocusableWidget):
  def __init__(self, map = None):
    FocusableWidget.__init__(self)
    widget.Widget.__init__(self, None)
    
    self.set_map(map)
    
  def set_map(self, map):
    self.map = map
    self.country = balazar.level.COUNTRIES[map.country_name]
    
    self.width  = (self.country.X2 - self.country.X1 + 1) * 50.0
    self.height = (self.country.Z2 - self.country.Z1 + 1) * 50.0
    
    self.left   = 5.0
    self.top    = 5.0
    
    self.tex_x = SIZE_2_TEX[self.country.X2 - self.country.X1 + 1]
    self.tex_z = SIZE_2_TEX[self.country.Z2 - self.country.Z1 + 1]
    
    self.material = soya.Material.get("item_map_%s" % self.country.name)
    
  def render(self):
    if self.map:
      hero  = tofu.GAME_INTERFACE.hero
      level = hero.level
      
      if (self.country.X1 <= level.X <= self.country.X2) and (self.country.Z1 <= level.Z <= self.country.Z2):
        self.material.activate()
        soyaopengl.glEnable(soyaopengl.GL_BLEND)

        soyaopengl.glBegin(soyaopengl.GL_QUADS)
        soyaopengl.glTexCoord2f(       0.0, self.tex_z); soyaopengl.glVertex2f(self.left             , self.top + self.height)
        soyaopengl.glTexCoord2f(self.tex_x, self.tex_z); soyaopengl.glVertex2f(self.left + self.width, self.top + self.height)
        soyaopengl.glTexCoord2f(self.tex_x,        0.0); soyaopengl.glVertex2f(self.left + self.width, self.top)
        soyaopengl.glTexCoord2f(       0.0,        0.0); soyaopengl.glVertex2f(self.left             , self.top)
        soyaopengl.glEnd()

        soyaopengl.glDisable(soyaopengl.GL_BLEND)
        soya.DEFAULT_MATERIAL.activate()

        soyaopengl.glColor4f(0.5, 0.0, 0.8, 1.0)
        soyaopengl.glBegin(soyaopengl.GL_QUADS)

        x = self.left
        x += (hero.x + balazar.level.BRIDGE_DEMI_DIM) / balazar.level.LEVEL_DIM * 50.0
        x += (level.X - self.country.X1) * 50.0

        z = self.top
        z += (hero.z + balazar.level.BRIDGE_DEMI_DIM) / balazar.level.LEVEL_DIM * 50.0
        z += (level.Z - self.country.Z1) * 50.0

        soyaopengl.glVertex2f(x - 2, z + 2)
        soyaopengl.glVertex2f(x + 2, z + 2)
        soyaopengl.glVertex2f(x + 2, z - 2)
        soyaopengl.glVertex2f(x - 2, z - 2)
        soyaopengl.glEnd()
        
  def key_down(self, key):
    if key == controller.CONTROL_QUIT:
      self.destroy()
      return 1
    
  def destroy(self):
    balazar.sound.play("menu1.wav")
    self.master.destroy()
  
