


class GamesObserver

  def initialize
=begin
    $igsClient.add_listener(IGSProtocol::MOVE){ |code,line| rec_move(line) }
    $igsClient.add_listener(IGSProtocol::STATUS){ |code,line| rec_status(line) }
    $igsClient.add_listener(IGSProtocol::GAMES){ |code,line| rec_game(line) }
    $igsClient.add_listener(IGSProtocol::INFO){ |code,line| rec_info(line) }
    $igsClient.add_listener(IGSProtocol::UNDO){ |code,line| rec_undo(line) }
    $igsClient.add_listener(IGSProtocol::ADJOURN){ |code,line| rec_adjourn(line) }
    $igsClient.add_listener(IGSProtocol::REMOVE){ |code,line| rec_remove(line) }
    $igsClient.add_listener(IGSProtocol::SCORE_M){ |code,line| rec_score(line) }
    $igsClient.add_listener(IGSProtocol::SAYGAME){ |code,line| rec_saygame(line) }
    $igsClient.add_listener(IGSProtocol::SAY){ |code,line| rec_say(line) }
    $igsClient.add_listener(IGSProtocol::TELL){ |code,line| rec_tell(line) }
    $igsClient.add_listener(IGSProtocol::KIBITZ){ |code,line| rec_kibitz(line) }
    $igsClient.add_listener(IGSProtocol::GAMENB){ |code,line| rec_gamenb(line) }
    $igsClient.add_listener(IGSProtocol::ERROR){ |code,line| rec_error(line) }
=end
    @gobans={}
    @undo_message = nil
    @match_number=nil
    @buf_status=[]
end

    #def rec_prompt
    #  find_game($user) { |game| game.ready }
    #end

def rec_gamenb(line)
  line =~ /^Game #(\d+)/
  @gamenb= $1.to_i
end

def rec_error(line)
  @gobans[@gamenb].rec_error(line) if @gobans.key?(@gamenb)
end

def rec_saygame(line)
  if line =~ /^Say in game (\d+)/
    @saynumber= $1.to_i
  end
end

def rec_say(line)
  if @gobans[@saynumber]
    @gobans[@saynumber].rec_message(line.strip,'say') 
    @saynumber= nil
  end
end

def rec_tell(line)
  res= /^\*(\S+)\*: (.*)/.match(line)

  if match=IGSCP.is_command(res[2])
    IGSCP.register_player(res[1],[res[2]])
    case IGSCP.family(match)
    when  'INFO'
      IGSCP.info(res[1],match)
    when 'CONTROL','MOVE'
    #debug IGSCP.number(match).to_i
      if (n=IGSCP.number(match).to_i) > 0 and @gobans.has_key?(n)
        @gobans[n].igscp_command(res[1],match) 
      else
        $stderr.puts("Received message for unknown game:\n"+line)
      end
    else
      IGSCP.send(res[1],'INFO:NOT_IMPLEMENTED')
    end
  elsif @gobans.key?(@match_number)
    @gobans[@match_number].rec_message(line,'tell')
  end
end

def rec_kibitz(line)
  if   line =~ /^Kibitz (.*): .*\[ *(\d+)\]$/
    @kibitz_player= $1
    @kibitz_number=$2.to_i
  else
    line.strip!
    if match= IGSCP.is_command(line)
      @gobans[@kibitz_number].igscp_command(@kibitz_player,match)
    else
      @gobans[@kibitz_number].rec_message("#@kibitz_player: #{line.strip}",'kibitz') if @gobans.key?(@kibitz_number)
    end
  end
end

def rec_move(buf)
  @header= GameHeader.new(buf.shift)
  if @gobans[@header.number].nil?
    if  @header.white == $user and @header.black == $user
      @gobans[@header.number]= GoTeacher.new(@header)
      @teach_number= @header.number
    elsif @header.white == $user or @header.black == $user
      @gobans[@header.number]= GoPlayer.new(@header)
      @match_number= @header.number
    elsif  $wallpaper_game == @header.number #or true; debug "ligne à changer !!!!"
      @gobans[@header.number]= WallPaper.new(@header)
    else
      @gobans[@header.number]= GoObserver.new(@header,@game_is_titled)
    end
    $igsClient.send('game ' + @header.number.to_s)
  else
    @gobans[@header.number].set_header(@header)
  end


  if gb=@gobans[@header.number]
   if buf.length > 0
    if buf.length > 1
      buf[0...-1].each { |line| 
	begin
	  move=Move.new(line)
	  gb.set_fast_move(move) 
	rescue
	debug $!
	debug line
	end
      }
     end
     gb.set_move(Move.new(buf[-1]))
     if  @fin_msg
       gb.game_finished(@fin_msg)
       @fin_msg=nil
       return # don't make 'ready'
     end
     if @buf_msg
       gb.set_blink(@buf_msg)
       @buf_msg=nil
     end
   end
   gb.ready
  end

  @game_is_titled=nil

end

def delete(number)
  @gobans.delete(number) if @gobans.key?(number)
end

def unobserve(number)
  $igsClient.send("unobserve #{number}") if  $igsClient
  @game_to_remove= number
end

def close_all
  @gobans.each_value { |gb| gb.quit }
  @gobans=nil
end

def rec_game(line)

  line =~  /^\[ *(.+)\] /
  return if $1 == '##'
  number = $1.to_i
  if @gobans.key?(number)
    if @game_to_remove and number == @game_to_remove
    else
      g= GameInfo.new(line)
      if @gobans.key?(g.number) and @gobans[g.number].game_info.nil?
        @gobans[g.number].set_info g
        $igsClient.send('moves '+ g.number.to_s)
      end
    end
  end
end

def rec_info(line)

  case line
  when /^\{Game/
      g= GameResult.new(line)

      if @gobans[g.number]
        unless @buf_status.empty?
          status = GameStatus.new(@buf_status) 
          @gobans[g.number].set_status(status) if status
          @buf_status=[]
        end
        @gobans[g.number].set_completed(g,line[1..-2]) 
        delete(g.number)
      end

  when /^(\S+) has resigned the game\./ ,
    /^(\S+) has run out of time./ 
  find_game($1) { |game|
    game.set_resigned(line)
    delete(game.number)
    @match_number= nil
  }
    #pas bon ca (code 21 pas 9): eh ben si 9 si teach
   when /^Game (\d+): .* has adjourned./
    #	debug line
    	  set_adjourned($1.to_i,line) 
  when /Game has been adjourned./

    if @teach_number
      if @gobans[ @teach_number]
        @gobans[ @teach_number].set_adjourned(line)
        delete( @teach_number)
        @teach_number=nil
      end
    end
  when /(\S+) has typed done/,/The player (\S+)/
    find_game($1) {|game|
      game.set_msg(line)
    }
     when /(\S+) wants the komi/
	find_game($1) {|game|
	   game.ask_komi(line)
	}
  when /Game will not count towards ratings/ 
    @gobans[@match_number].igs_set_free(line)  if @gobans.key?(@match_number)
  when /Game will count towards ratings/ 
    @gobans[@match_number].igs_set_rated(line)  if @gobans.key?(@match_number)
  when /Increase (\S+)'s time by (\d+) minute/ #'
    find_game($1) { |game|
      game.addtime(line,$1,$2.to_i)  
      game.set_msg(line)  
    }
  when /check your score/
    @fin_msg=line
    # comment on fait en multiple game ?
  when /You have/
    @buf_msg=line
  when /Board is restored to what it was when you started scoring/
    @gobans.each_value {  | game | 
      if game.white == $user or game.black == $user
        if game.game_over
          game.set_msg(line)
          game.del_remove
        end
      end
    }

  when /Removing game (\d+) from observation list./
    delete($1.to_i)
    @game_to_remove= nil
    #when /Removing @/
  when /Your opponent has lost/
    @buf_adjourned= line
  when /You have marks at/
    @gobans[@teach_number].set_msg(line) if @gobans[@teach_number]
  when /Set the komi to (\d*\.\d)/
    if @gobans[@match_number]
      @gobans[@match_number].set_msg(line)
      @gobans[@match_number].igs_set_komi($1)
    end
  when /Game is titled: (.*)/
    @game_is_titled= $1
  else
  end
end

    # faire un each_game
def find_game(player)
  @gobans.each_value {  | game | 
    if game.white ==  player or game.black == player
      yield(game)
    end
  }

end

def rec_shout(line)
  if line =~ /Game (\d+): .* has adjourned./

    set_adjourned($1.to_i,line) 
  end
end

def rec_score(line)
  if @buf_status
    g= GameResult.new(line)

    number=-1
    @gobans.each_value {  | game | 
      if game.white ==  g.w_player and game.black == g.b_player
        number= game.number
        break
      end
    }

    if number > -1
      status = GameStatus.new(@buf_status)
      @gobans[number].set_status(status) if status
      @gobans[number].set_completed(g,line) 
      delete(number)
    end
    @buf_status=[]
    @match_number= nil
  end
end

def rec_status(line)
  @buf_status.push(line)
end

def rec_undo(line)
    #@undo_message = line 

  if line=~ /(\S+) undid the last move \((.*)\)/
    @gobans.each_value {  | game | 
      if game.white == $1 or game.black == $1
        game.undo(line)
      end
    }
  elsif line =~ /Undo in game (\d+):.*: +(\S+)/
    @gobans[$1.to_i].undo(line)
  end
end

def set_adjourned(number,line)

  if @gobans[number]
    @gobans[number].set_adjourned(line)
    delete(number)
  end

end

    #48 Game 70 mosul requests an adjournment
    #48 Game 48 has been adjourned by akiraf
def rec_adjourn(line)

  line =~ /^Game (\d+) (.*)/
  number = $1.to_i
  msg= $2
  if msg =~ /has been adjourned/
    if @gobans[number]
      if @buf_adjourned
        @gobans[number].set_lost_connection(@buf_adjourned) 
        @buf_adjourned=nil
      end
      @gobans[number].set_adjourned(line)
      delete(number)
      @match_number= nil if number ==  @match_number
    end
  else
    if @gobans[number]
      @gobans[number].set_blink(msg)
    end
  end
end

def rec_remove(line)
  line =~ /^Game (\d+) .*/
  number = $1.to_i
  @gobans[number].set_removing(line) if @gobans[number]
    # @gobans[number].set_msg(line) unless @gobans[number].nil?
end

end




