# Balazar Brothers
# Copyright (C) 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 cerealizer, soya, tofu, soya.tofu4soya as tofu4soya, balazar_brothers

import balazar_brothers.globdef as globdef
from balazar_brothers.character import Character, Balazar
from balazar_brothers.platform  import Platform, PortailPlatform, StartingPlatform

def level_display_name(level_name):
  x = level_name.rfind("_")
  return _(level_name[:x]) + " " + level_name[x + 1:]

MUSICS = {
  "tutorial"         : "oceane.ogg",
  "pompon_forest"    : "pompon.ogg",
  "coqueliform_field": "oceane.ogg",
  }

class Level(tofu4soya.Level):
  def __init__(self):
    tofu4soya.Level.__init__(self)
    
    self.center      = soya.Point(self)
    self.static_part = soya.World(self)
    
    self.hour    = 8.0
    self.weather = "sun"
    self.land    = None

  def get_country_name(self): return self.filename[:self.filename.rfind("_")]
  def set_active(self, active):
    tofu4soya.Level.set_active(self, active)
    
    balazar_brothers.sound.play_music(MUSICS[self.get_country_name()])
    
  def begin_round(self):
    tofu4soya.Level.begin_round(self)
    
  def advance_time(self, proportion):
    tofu4soya.Level.advance_time(self, proportion)
    
  def big_round(self):
    for child in self.children:
      if hasattr(child, "big_round"): child.big_round()
      
  def add_mobile(self, mobile):
    if isinstance(mobile, Balazar) and mobile.previous_level_name:
      if   mobile.previous_level_name == "__new_perso__":
        starting_platform = self.get_by_class(StartingPlatform) or self.get_by_class(PortailPlatform) 
      elif mobile.previous_level_name:
        for starting_platform in self.get_all_by_class(PortailPlatform):
          if starting_platform.next_level_name == mobile.previous_level_name:
            break
        else: starting_platform = self.get_by_class(StartingPlatform)
        
      mobile.set_platform(starting_platform, change_level = 0)
      mobile.previous_level_name = None
      
    elif isinstance(mobile, Character) and mobile.platform and not mobile in mobile.platform.characters_on:
      mobile.platform.add_character(mobile, 0)
      
    tofu4soya.Level.add_mobile(self, mobile)
    
  def remove_mobile(self, mobile):
    if isinstance(mobile, Character):
      if mobile.platform and not (isinstance(mobile.platform, Character) and mobile.player_name == mobile.platform.player_name):
        
        mobile.platform.remove_character(mobile)
        
        for character_on in mobile.characters_on:
          mobile.remove_character(character_on)
          character_on.set_platform(mobile.platform)
          
    tofu4soya.Level.remove_mobile(self, mobile)
    
  def add_or_add_mobile(self, o):
    if isinstance(o, tofu.Mobile): self.add_mobile(o)
    else: self.add(o)
    
  def del_or_del_mobile(self, i):
    o = self.children[i]
    if isinstance(o, tofu.Mobile): self.remove_mobile(o)
    else: del self[i]
    
  def get_by_class(self, Class):
    for i in self:
      if isinstance(i, Class): return i

  def get_all_by_class(self, Class):
    return [i for i in self if isinstance(i, Class)]
      
  def build_ended(self):
    self.center.set_xyz(0.0, 0.0, 0.0)
    
    nb = 0
    for platform in self.mobiles:
      if isinstance(platform, Platform):
        nb += 1
        self.center.add_xyz(platform.x, platform.y, platform.z)

    if nb:
      self.center.x /= nb
      self.center.y /= nb
      self.center.z /= nb
      
    for i in self.recursive():
      if isinstance(i, soya.Land): i.reinit()
      
  #def get(clazz, filename):
  #  if filename == "demo" : return create_demo_level ()
  #  if filename == "demo2": return create_demo_level2()
  #get = classmethod(get)
  
  def random_land(self):
    from balazar_brothers.land_gen import random_land
    
    if self.land: self.land.parent.remove(self.land)
    
    if self.filename.startswith("coqueliform_field"):
      self.land = random_land(self)
      self.land.set_xyz(-32.0 * 1.25, -30.0, -32.0 * 1.25)
      self.land.set_material_layer(soya.Material.get("grass"              ), 0.0  * 50.0, 0.24 * 50.0)
      self.land.set_material_layer(soya.Material.get("coqueliformes_champ"), 0.24 * 50.0, 0.54 * 50.0)
      self.land.set_material_layer(soya.Material.get("snow"               ), 0.54 * 50.0, 0.6  * 50.0)
      self.land.set_material_layer(soya.Material.get("ice"                ), 0.6  * 50.0, 1.0  * 50.0)
    elif self.filename.startswith("fountain"):
      self.land = random_land(self, default_max_y = 0.21, pic_proba = 0.3, plateau_proba = 0.2, colline_proba = 0.5, cratere1_proba = 0.0, cratere2_proba = 0.0, monticule_proba = 0.0, termitiere_proba = 0.0)
      self.land.set_xyz(-32.0 * 1.25, -30.0, -32.0 * 1.25)
      self.land.set_material_layer(soya.Material.get("nacre"   ), 0.0  * 50.0, 0.4 * 50.0)
      self.land.set_material_layer(soya.Material.get("grass"   ), 0.4  * 50.0, 1.0 * 50.0)
    elif self.filename.startswith("pompon_forest"):
      self.land = random_land(self, default_max_y = 0.25, pic_proba = 0.3, plateau_proba = 0.6, colline_proba = 0.2, cratere1_proba = 0.7, cratere2_proba = 0.7, monticule_proba = 0.8, termitiere_proba = 0.4)
      self.land.set_xyz(-32.0 * 1.25, -30.0, -32.0 * 1.25)
      self.land.set_material_layer(soya.Material.get("feuillesmortes2"), 0.0  * 50.0, 0.26 * 50.0)
      self.land.set_material_layer(soya.Material.get("feuillesmortes3"), 0.26 * 50.0, 0.3 * 50.0)
      self.land.set_material_layer(soya.Material.get("grass"          ), 0.3  * 50.0, 0.5 * 50.0)
      self.land.set_material_layer(soya.Material.get("grass3"         ), 0.5  * 50.0, 1.0 * 50.0)
    else:
      self.land = random_land(self, default_max_y = 0.27, pic_proba = 0.0, plateau_proba = 0.8, colline_proba = 0.5, cratere1_proba = 0.5, cratere2_proba = 0.5, monticule_proba = 0.0, termitiere_proba = 0.0)
      self.land.set_xyz(-32.0 * 1.25, -30.0, -32.0 * 1.25)
      self.land.set_material_layer(soya.Material.get("feuillesmortes"), 0.0   * 50.0, 0.28 * 50.0)
      self.land.set_material_layer(soya.Material.get("grass2"        ), 0.28  * 50.0, 0.4  * 50.0)
      self.land.set_material_layer(soya.Material.get("grass"         ), 0.4   * 50.0, 1.0  * 50.0)
      
  def save(self):
    if globdef.mode == "--level-editor": # Hack !!!
      self.build_ended()
      
    tofu4soya.Level.save(self)
cerealizer.register(Level, tofu.SavedInAPathHandler(Level))



def create_demo_level():
  if Level._alls2.has_key("demo"): return Level._alls2["demo"]
  
  print "Create level demo..."
  
  level = Level()
  level.filename = "demo"
  
  from soya import Point, Vector
  from balazar_brothers.platform import PortailPlatform, StartingPlatform, Coqueliform, RotatingCoqueliform
  from balazar_brothers.land_gen import random_land
  
  def create(Class, position = None, front = None, **kargs):
    p = Class(**kargs)
    level.add_mobile(p)
    if position: p.move(position)
    if front   : p.look_at(front)
    return p
  
  
  p = create(StartingPlatform, Point(None,  0.0, 0.0,  0.0))
  p = create(Coqueliform     , Point(None,  1.0, 0.0, -4.0))
  #p = create(Coqueliform     , Point(None, -1.0, 0.0, -8.0))
  p = create(PortailPlatform     , Point(None, -1.0, 0.0, -8.0), next_level_name = "demo2")
  p = create(RotatingCoqueliform, Point(None, -4.0, 0.0, -10.0))
  p = create(Coqueliform     , Point(None, -6.5, 1.0, -11.0))
  p = create(Coqueliform     , Point(None, -10.0, 2.0, -11.5))
  p = create(Coqueliform     , Point(None, -14.0, 2.5, -11.0))
  p = create(Coqueliform     , Point(None, -17.0, 3.0, -9.5))
  p = create(Coqueliform     , Point(None, -18.0, 3.0, -7.0))
  p = create(Coqueliform     , Point(None, -18.5, 3.2, -4.0))
  p = create(Coqueliform     , Point(None, -18.0, 3.5, -1.0))
  p = create(Coqueliform     , Point(None, -17.0, 3.5,  1.0))
  p = create(Coqueliform     , Point(None, -14.5, 3.7,  2.0))
  p = create(Coqueliform     , Point(None, -12.0, 0.0,  3.0))
  p = create(Coqueliform     , Point(None, -8.5, 0.0,  3.5))
  p = create(Coqueliform     , Point(None, -4.5, 0.0,  2.5))
  p = create(Coqueliform     , Point(None, -2.0, 0.0,  1.5))

  level.weather = "sun"
  level.hour    = 8.0
  
  land = random_land(level)
  land.x = -50.0
  land.z = -50.0
  
  #land.set_material_layer(soya.Material.get("grass2"), 0.0  * 50.0, 0.24 * 50.0)
  land.set_material_layer(soya.Material.get("grass"), 0.0  * 50.0, 0.24 * 50.0)
  land.set_material_layer(soya.Material.get("coqueliformes_champ" ), 0.24 * 50.0, 0.54 * 50.0)
  land.set_material_layer(soya.Material.get("snow"  ), 0.54 * 50.0, 0.6  * 50.0)
  land.set_material_layer(soya.Material.get("ice"   ), 0.6  * 50.0, 1.0  * 50.0)
  
  
  level.build_ended()
  return level



def create_demo_level2():
  if Level._alls2.has_key("demo2"): return Level._alls2["demo2"]
  
  print "Create level demo2..."
  
  level = Level()
  level.filename = "demo2"
  
  from soya import Point, Vector
  from balazar_brothers.platform import PortailPlatform, StartingPlatform, Coqueliform, RotatingCoqueliform
  from balazar_brothers.bonus    import SmallChest, BigChest
  from balazar_brothers.land_gen import random_land
  
  def create(Class, position = None, front = None, **kargs):
    p = Class(**kargs)
    level.add_mobile(p)
    if position: p.move(position)
    if front   : p.look_at(front)
    return p
  
  p = create(PortailPlatform , Point(None,  0.0, 0.0,  0.0), next_level_name = "demo")
  p = create(Coqueliform     , Point(None,  1.0, 0.0, -4.0))
  p = create(Coqueliform     , Point(None, -1.0, 0.0, -8.0))
  p = create(RotatingCoqueliform, Point(None, -4.0, 0.0, -10.0))
  
  p = create(BigChest, Point(None,  -1.0, 4.0, -8.0))
  
  level.weather = "sun"
  level.hour    = 17.0
  
  land = random_land(level)
  land.x = -50.0
  land.z = -50.0
  
  #land.set_material_layer(soya.Material.get("grass2"), 0.0  * 50.0, 0.24 * 50.0)
  land.set_material_layer(soya.Material.get("grass"), 0.0  * 50.0, 0.24 * 50.0)
  land.set_material_layer(soya.Material.get("coqueliformes_champ" ), 0.24 * 50.0, 0.54 * 50.0)
  land.set_material_layer(soya.Material.get("snow"  ), 0.54 * 50.0, 0.6  * 50.0)
  land.set_material_layer(soya.Material.get("ice"   ), 0.6  * 50.0, 1.0  * 50.0)
  
  level.build_ended()
  return level
