# -*- coding: latin-1 -*-
# Balazar Brothers
# Copyright (C) 2003-2006 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 cerealizer, tofu, soya, soya.sdlconst as sdlconst, soya.tofu4soya as tofu4soya, soya._soya, soya.widget as widget, soya.opengl as opengl
import balazar_brothers, balazar_brothers.sound, balazar_brothers.globdef as globdef, balazar_brothers.controller as controller
from balazar_brothers.camera     import Traveling
from balazar_brothers.weather    import WeatherAtmosphere
from balazar_brothers.discussion import Bubble


def init():
  if not soya.inited:
    soya.init(title = "Balazar Brothers", 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.render()
  soya.root_widget = None
  

class Idler(tofu4soya.Idler):
  def __init__(self, scene = None):
    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)
    
    tofu4soya.Idler.begin_round(self)
    
    if self.big_round_count == 0:
      self.big_round_count = 30
      for scene in self.scenes: scene.big_round()
    else: self.big_round_count -= 1
    
  def add_level(self, level):
    tofu4soya.Idler.add_level(self, level)

    self.scenes[0].atmosphere.set_time_and_weather(level.hour, level.weather)

class Replay2VideoIdler(Idler):
  #def __init__(self, scene = None):
  #  Idler.__init__(self, scene)
    
  #def begin_round(self):
  #  Idler.begin_round(self)
    
  def idle(self):
    self.running     = 1
    self.will_render = 1
    i = 0
    while self.running:
      for f in self.next_round_tasks[:]:
        f()
        del self.next_round_tasks[0]
      self.begin_round()
      self.advance_time(0.5)
      self.advance_time(0.5)
      self.end_round()
      self.render()
      
      soya.screenshot().save(os.path.join(globdef.IMG_DIR, "img_%05d.png" % i))
      i += 1
      
      #import time; time.sleep(0.03)
    return self.return_value

class Scene(soya.World):
  def __init__(self):
    soya.World.__init__(self)
    if globdef.mode != "--server": self.listener = controller.EventListener(self)
    
    self.camera     = None
    self.atmosphere = WeatherAtmosphere(self)
    
  def big_round(self):
    for child in self.children:
      if hasattr(child, "big_round"): child.big_round()
      
  def begin_round(self):
    soya.World.begin_round(self)
    
    self.atmosphere.begin_round()
    
  def advance_time(self, proportion):
    soya.World.advance_time(self, proportion)
    
    self.atmosphere.advance_time(proportion)
    
    
def set_path_current(player_filename, enable):
  d = os.path.join(globdef.SAVED_GAME_DIR, player_filename)
  globdef.check_path(d)
  globdef.check_path(os.path.join(d, "players"))
  globdef.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 = "", IdlerClass = Idler):
  globdef.mode = "--single"
  scene = Scene()
  IdlerClass(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_brothers.sound.end_music()
  if scene.listener.replay: scene.listener.replay.save()
  return r

  
def start_server():
  globdef.mode = "--server"
  scene = Scene()
  Idler(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_brothers.sound.end_music()
  return r
  

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

    self.camera = soya.IDLER.scenes[0].camera = soya.TravelingCamera(soya.IDLER.scenes[0])
    self.camera.back = 100.0
    self.camera.speed = 0.03
    #self.camera.add_traveling(soya.FixTraveling(soya.Point(self.camera.parent, 14.0, 8.0, -5.0), soya.Point(self.camera.parent, 0.0, 5.0, -5.0)))
    self.traveling = Traveling()
    self.camera.add_traveling(self.traveling)
    
    balazar_brothers.sound.init(self.camera)
    self.root_widget = widget.Group()
    self.root_widget.add(self.camera)
    soya.set_root_widget(self.root_widget)
    if globdef.FPS_LABEL: soya.widget.FPSLabel(self.root_widget)
    
    self.score_label = ImageLabel(self.root_widget, None, "score", soya.Material.get("coffre2D"), 0)
    self.keys_label  = ImageLabel(self.root_widget, None, "keys" , soya.Material.get("clef2D"  ), 1)
    
    self.left_bubble   = Bubble(self.root_widget, -1, "test -1", (1.0, 0.0, 0.0, 1.0))
    self.middle_bubble = Bubble(self.root_widget,  0, "test  0", (0.0, 0.0, 0.0, 1.0))
    self.right_bubble  = Bubble(self.root_widget,  1, "", (0.0, 0.0, 1.0, 1.0))
    
  def network_error(self, reason):
    soya.IDLER.stop(reason)
    
  def ready(self, notifier):
    tofu4soya.GameInterface.ready(self, notifier)
    
    self.notifier.login_player(self.login, self.password)
    
INDIGO_JOKER_FONT = soya.Font(os.path.join(globdef.APPDIR, "fonts", "indigo.ttf"), 30, 30)
import balazar_brothers.platform
balazar_brothers.platform.Label3D._font = INDIGO_JOKER_FONT # Hack !
  

class ImageLabel(widget.Label):
  def __init__(self, master = None, character = None, attr = "", material = None, pos = 0):
    self.character = character
    self.attr      = attr
    self.material  = material
    self.pos       = pos
    
    widget.Label.__init__(self, master, font = INDIGO_JOKER_FONT, align = 0)
    
    self.old      = getattr(character, attr, 0)
    self.text     = unicode(self.old)

  def set_text(self, text):
    widget.Label.set_text(self, text)
    
    self.resize(self.master.left, self.master.top, self.master.width, self.master.height)
  text = property(widget.Label.get_text, set_text)
  
  def build_display_list(self):
    widget.Label.build_display_list(self)
    
    self.material.activate()
    opengl.glEnable(opengl.GL_BLEND)
    
    opengl.glBegin(opengl.GL_QUADS)
    opengl.glTexCoord2f(0.0, 0.0); opengl.glVertex2f(self.left + self.width - 50, self.top     )
    opengl.glTexCoord2f(0.0, 1.0); opengl.glVertex2f(self.left + self.width - 50, self.top + 50)
    opengl.glTexCoord2f(1.0, 1.0); opengl.glVertex2f(self.left + self.width     , self.top + 50)
    opengl.glTexCoord2f(1.0, 0.0); opengl.glVertex2f(self.left + self.width     , self.top     )
    opengl.glEnd()
    
    soya.DEFAULT_MATERIAL.activate()
    opengl.glDisable(opengl.GL_BLEND)
    
  def widget_begin_round(self):
    dif = getattr(self.character, self.attr, 0) - self.old
    if   dif > 0:
      self.old += 1
      self.text = unicode(self.old)
      
    elif dif < 0:
      self.old -= 1
      self.text = unicode(self.old)
      
  def resize(self, parent_left, parent_top, parent_width, parent_height):
    w, h = self.font.get_print_size(self._text)
    
    self.left   = parent_left + parent_width  - 10 - 50 - w
    self.top    = 5 + 52 * self.pos
    self.width  = 50 + 5 + w
    self.height = 50
    self._changed = -2

