# Follow Line Board module
import gobject
import gnomecanvas
import gcompris
import gcompris.skin
import gcompris.bonus
import gcompris.utils
import gtk
import gtk.gdk
import random
import math
from gettext import gettext as _

# ----------------------------------------
#

class Gcompris_followline:
  """follow the line"""


  def __init__(self, gcomprisBoard):
    self.gcomprisBoard = gcomprisBoard

    # These are used to let us restart only after the bonus is displayed.
    # When the bonus is displayed, it call us first with pause(1) and then with pause(0)
    self.board_paused  = 0;
    self.gamewon       = 0;

    self.loosing_count = 0

    self.color_empty   = 0xcee871FFL
    self.color_full    = 0x1a24cbffL
    self.color_target  = 0xFF0000FFL
    self.color_border  = 0x101010FFL

    print("Gcompris_followline __init__.")


  def start(self):
    self.gcomprisBoard.level=1
    self.gcomprisBoard.maxlevel=9
    self.gcomprisBoard.sublevel=1
    self.gcomprisBoard.number_of_sublevel=1
    gcompris.bar_set(gcompris.BAR_LEVEL)
    self.background_item = gcompris.set_background(self.gcomprisBoard.canvas.root(),
                                                   "images/followline.png")
    self.background_item_connect_id = self.background_item.connect("event", self.loosing_item_event)

    gcompris.bar_set_level(self.gcomprisBoard)

    self.init_board()

    print("Gcompris_followline start.")


  def end(self):

    # Remove the root item removes all the others inside it
    self.cleanup()

    # Disconnect from the background item
    self.background_item.disconnect(self.background_item_connect_id)

  def ok(self):
    print("Gcompris_followline ok.")


  def repeat(self):
    print("Gcompris_followline repeat.")


  def config(self):
    print("Gcompris_followline config.")


  def key_press(self, keyval, commit_str, preedit_str):
    return False


  # Called by gcompris core
  def pause(self, pause):

    self.board_paused = pause

    # When the bonus is displayed, it call us first with pause(1) and then with pause(0)
    # the game is won
    if(pause == 0):
      self.next_level()
      self.gamewon = 0

    return


  # Called by gcompris when the user click on the level icon
  def set_level(self, level):
    self.gcomprisBoard.level=level
    self.gcomprisBoard.sublevel=1
    self.next_level()

  # End of Initialisation
  # ---------------------

  def cleanup(self):
    # Remove the root item removes all the others inside it
    self.state = "Done"

    self.rootitem.destroy()
    self.lines_group.destroy()
    self.water_spot_group.destroy()

  def next_level(self):

    self.cleanup()

    # Set the level in the control bar
    gcompris.bar_set_level(self.gcomprisBoard);

    self.init_board()



  def init_board(self):

    self.state = "Ready"

    # Create our rootitem. We put each canvas item in it so at the end we
    # only have to kill it. The canvas deletes all the items it contains automaticaly.
    self.rootitem = self.gcomprisBoard.canvas.root().add(
      gnomecanvas.CanvasGroup,
      x=0.0,
      y=0.0
      )

    # Another group where we put each canvas line item in it
    self.lines_group = self.gcomprisBoard.canvas.root().add(
      gnomecanvas.CanvasGroup,
      x=0.0,
      y=0.0
      )

    start_x         = 40
    start_y         = gcompris.BOARD_HEIGHT/2
    stop_x          = gcompris.BOARD_WIDTH - 100

    # Line path (create several little line)
    min_boundary = 40
    y            = start_y
    line_width   = 45 - self.gcomprisBoard.level*2
    step         = (stop_x-start_x)/(30)

    frequency = 1 + int(self.gcomprisBoard.level/4)

    xpi = math.pi/2*frequency
    y   = start_y + math.cos(xpi)*(self.gcomprisBoard.level*10)
    for x in range(start_x, stop_x, step):

      xpi += (math.pi/2*frequency)/step
      y2 = start_y + math.cos(xpi)*(self.gcomprisBoard.level*10)

      # Check we stay within boundaries
      if(y2>=gcompris.BOARD_HEIGHT-min_boundary):
        y2=gcompris.BOARD_HEIGHT-min_boundary
      elif(y2<=min_boundary):
        y2=min_boundary

      item = self.lines_group.add(
        gnomecanvas.CanvasLine,
        points          =( x,
                           y,
                           x + step,
                           y2),
        fill_color_rgba = self.color_empty,
        width_units     = line_width,
        cap_style       = gtk.gdk.CAP_ROUND
        )
      item.connect("event", self.line_item_event)

      if x > start_x and x < stop_x-step:
        self.rootitem.add(
          gnomecanvas.CanvasLine,
          points          =( x,
                             y,
                             x + step,
                             y2),
          fill_color_rgba = self.color_border,
          width_units     = line_width + 20,
          cap_style       = gtk.gdk.CAP_ROUND
          )

      y = y2

    self.highlight_next_line()

    # Another group where we put each canvas line item in it
    self.water_spot_group = self.gcomprisBoard.canvas.root().add(
      gnomecanvas.CanvasGroup,
      x=0.0,
      y=0.0
      )
    # A water spot will be displayed when the user win
    self.water_spot = self.water_spot_group.add (
      gnomecanvas.CanvasPixbuf,
      pixbuf = gcompris.utils.load_pixmap("images/water_spot.png"),
      x=580,
      y=260,
      )
    self.water_spot.hide()


  # Code that increments the sublevel and level
  # And bail out if no more levels are available
  # return 1 if continue, 0 if bail out
  def increment_level(self):
    self.gcomprisBoard.sublevel += 1

    if(self.gcomprisBoard.sublevel>self.gcomprisBoard.number_of_sublevel):
      # Try the next level
      self.gcomprisBoard.sublevel=1
      self.gcomprisBoard.level += 1
      if(self.gcomprisBoard.level>self.gcomprisBoard.maxlevel):
        # the current board is finished : bail out
        gcompris.bonus.board_finished(gcompris.bonus.FINISHED_RANDOM)
        return 0

    return 1

  #
  # Highlight the next spot on the line
  #
  def highlight_next_line(self):
    for item in self.lines_group.item_list:
      if(item.get_data("gotit") != True):
        item.set(
          fill_color_rgba = self.color_target,
          )
        item.set_data("iamnext", True);
        return

  #
  # Highlight the previous spot on the line
  # Called on loose situation
  #
  def highlight_previous_line(self):
    previous_item = []

    for item in self.lines_group.item_list:

      if(item.get_data("iamnext") == True):

        if(previous_item):
          # Remove the target info for this item
          item.set_data("iamnext", False)
          item.set(
            fill_color_rgba = self.color_empty,
            )

          # Set the target info on the previous item
          previous_item.set(
            fill_color_rgba = self.color_target,
            )
          item.set_data("gotit", False)
          previous_item.set_data("iamnext", True);

        return

      previous_item = item


  def is_done(self):
    done = True
    for item in self.lines_group.item_list:
      if(item.get_data("gotit") != True):
        done = False

    if(done):
      # This is a win
      if (self.increment_level() == 1):
        self.state = "Done"
        self.gamewon = 1
        self.water_spot.raise_to_top()
        self.water_spot.show()
        gcompris.bonus.display(gcompris.bonus.WIN, gcompris.bonus.FLOWER)

    return done

  def loosing_item_event(self, widget, event=None):
    if(self.state == "Started"):
      self.loosing_count += 1
      if(self.loosing_count % 10):
        self.highlight_previous_line()
    return False


  def line_item_event(self, widget, event=None):
    if not self.board_paused and widget.get_data("iamnext") == True:
      # The first line touch means the game is started
      self.state = "Started"
      widget.set(
        fill_color_rgba = self.color_full,
        )
      widget.set_data("gotit", True);
      widget.set_data("iamnext", False);
      self.highlight_next_line()
      self.is_done()

    return False

