


class IGSSocket
  attr_reader :socket, :banner

  def initialize(server,port,user,pass)
    @banner=''

    @socket=TCPsocket.new(server,port)

    waitfor(/Login: /)
    @socket.puts user
    waitfor(/1 1|Password: |#> /)

    if  @lastline =~ /1 1/
      raise(RuntimeError,"Need password") if pass.nil?
      @socket.puts(pass)
    elsif  @lastline =~ /Password: /
      raise(RuntimeError, "Need password") if pass.nil?
      @socket.puts(pass)
      waitfor(/#> /)
    elsif @lastline =~ /#>/
    end

    @socket.puts('toggle client on')
#       @socket.puts "id RubyGo-#$version #{RUBY_VERSION} #{RUBY_PLATFORM}"
  end

  def waitfor(str)
    reply = ''
    until reply =~ str
      c = @socket.getc
      raise(IOError,"Socket not opened") if c.nil?
      next if c > 127 or c == 1
      reply << c unless c == ?\r
      if c == ?\n
        @banner << reply
        @lastline = reply
        reply = ''
        $stdout.flush
      end
    end
    @lastline=reply
    #$stdout.flush
  end

end

class IGSClient

  def initialize(server)
    @server=server
    @arr_server = [@server]
    @Recv_file = false
    @cmd_stack = []
    @listeners=Hash.new
    @console_cb=nil
    @buf_input = ''
    @in_file= false
    $server_ready=true
    @bytes=0
    @message=''
    @buf_players= []

	$lag = 0

   @timeout = TkAfter.new( Defaults::DEFS['connection_timeout']  *60000, 1, proc{alert_timeout}).start
    TkAfter.new(1000,-1,proc {send}).start
  end

  def alert_timeout

    unless Defaults::DEFS['connection_keep_alive']
      Misc.warning("You have been idle for #{ Defaults::DEFS['connection_timeout']} minutes
please click 'OK' to stay connected")
    end
    @timeout = TkAfter.new( Defaults::DEFS['connection_timeout'] * 60000 , 1, proc{alert_timeout}).start
    send("ayt")
  end

  def close
    @server.puts 'exit'
    @server.close
    @timeout.stop
    $logfile.close unless $logfile.nil?
  end

  if  $0 =~ /client\.rb/

    def getlines
      while select(@arr_server,nil,nil,0) and not eof?
        str=@server.gets("\n").chop

        $logfile.puts str+"\r" if $logfile
  #  puts str+':'
        parse_line(str)
      end
    end

  else

    def getlines
# if $igsClientreturn if @server.nil?

#orig= Tk.clock_clicks
      count=0

      while select(@arr_server,nil,nil,0) and not eof?
        str=@server.gets("\r\n").chop

        $logfile.puts str+"\r" if $logfile
  #  puts ':'+str
        parse_line(str)
        count +=1
      end
 if count > 0
      $console.set_netperf(count )
	$lag = 0
else
	$lag += 1
# 30 s
 	if $lag > 3000 and $console.quiet.value == '0' # et quiet off
		#Misc.warning("alert : server not responding !")
		$console.putline("alert : server not responding !",'error')
		$lag = 0
	end
end

      Tk.update

#$ip._eval('after 100 ruby igsclient_readlines')




=begin
      fin=Tk.clock_clicks
      total= fin - orig
      total= total/ 1000000.0
      debug total
=end
  end
end

def parse_line(line)
  str=''
  code = 0
  if line.empty?
  elsif not line.scan(/^(\d+) (.*)/).empty?
  #  raise Badline.new( '"'+line+'"')  if reg[0].nil?
    code = $1.to_i
    do_callbacks(code,$2)

    if code  == 1
      $server_ready = true
      $console.display_ready	true
      Tk.update
      #  send # see if there is some cmd waiting
    else
      $server_ready = false
    end
  else
    do_callbacks(8,line)
  end
end


def do_callbacks(code,line)
#puts "(igsclient 155):#{code} -> #{line}"
  begin
#  unless code == IGSProtocol::IGS or code == IGSProtocol::USER or code == IGSProtocol::GAMES or code == IGSProtocol::MOVE
#    $console.receive(code,line)
#  end
    case code
    when IGSProtocol::PROMPT
      $gameslist.rec_prompt
		$wlist.refresh
      unless @message.empty?
        Misc.info(@message)
        @message = ''
      end
      if  @moves_buf 
        $gamesobserver.rec_move(@moves_buf)
        @moves_buf=nil
      end
      unless @buf_players.empty?
		$wlist.rec_players(@buf_players)
        $playerslist.rec_status(@buf_players)
        @buf_players= []
      end
    when IGSProtocol::DOWN
      $console.receive(code,line)
      @message << line << "\n"
    when IGSProtocol::MOVE
      if @moves_buf
        @moves_buf << line
      else
        @moves_buf= [line]
      end
#    $gamesobserver.rec_move(line)
    when IGSProtocol::STATUS
      $gamesobserver.rec_status(line)
    when IGSProtocol::GAMES
      $gamesobserver.rec_game(line)
      $gameslist.rec_status(line)
		$wlist.rec_game(line)
    when IGSProtocol::INFO
      $console.receive(code,line)
      $gamesobserver.rec_info(line)
      $statobserver.rec_info(line)
      $playerslist.rec_info(line)
    when IGSProtocol::UNDO
      $gamesobserver.rec_undo(line)
    when IGSProtocol::ADJOURN
      $gamesobserver.rec_adjourn(line)
    when IGSProtocol::REMOVING
      $gamesobserver.rec_remove(line)
    when IGSProtocol::SCORE_M
      $gamesobserver.rec_score(line)
    when IGSProtocol::SAY_MG
      $gamesobserver.rec_saygame(line)
    when IGSProtocol::SAY
      $gamesobserver.rec_say(line)
    when IGSProtocol::TELL
      $console.receive(code,line)
      $gamesobserver.rec_tell(line)
      $chatobserver.rec_tell(line)
    when IGSProtocol::KIBITZ
      $gamesobserver.rec_kibitz(line)
    when IGSProtocol::GOERR
      $gamesobserver.rec_gamenb(line)
    when IGSProtocol::ERROR
      $console.receive(code,line)
      $gamesobserver.rec_error(line)
    when IGSProtocol::YELL
      $chatobserver.rec_yell(line)
    when IGSProtocol::SHOUT
      $console.receive(code,line)
      $gameslist.rec_shout(line)
      $playerslist.rec_shout(line)
      $gamesobserver.rec_shout(line)
      $chatobserver.rec_shout(line)
    when IGSProtocol::USER
      @buf_players.push(line)
    when IGSProtocol::IGS
      $playerslist.rec_user_list(line)
    when IGSProtocol::HELP
      $console.receive(code,line)
    when IGSProtocol::VERSION
      $console.receive(code,line)
    when IGSProtocol::SAVED
      $console.receive(code,line)
    when IGSProtocol::WHO
      $console.receive(code,line)
    when IGSProtocol::BEEP
    when IGSProtocol::DOT
    when IGSProtocol::THIST
    when IGSProtocol::SGF_F
      $console.receive(code,line)
    when IGSProtocol::AUTOASK
      $console.receive(code,line)
    when IGSProtocol::MESSAGE
      $console.receive(code,line)
	when 'banner'
	$console.receive(IGSProtocol::HELP,line)
    else
      $stderr.puts "unknown code:\n#{code} #{line}"
    end
  rescue
    debug "error in callback"
    puts $!
    puts $@
  end
end

def old_do_callbacks(code,line)
  begin
    @console_cb.call(code,line)  unless @console_cb.nil?

    @listeners[code].each { |cbproc|
      cbproc.call(code,line)
    } if @listeners.key?(code)

  rescue
    debug "error in callback"
    puts $!
    puts $@
  end
end

def send(cmd = nil)

     # debug cmd if cmd
  @cmd_stack.push(cmd) if  cmd
  if  $server_ready and not @cmd_stack.empty? and select(nil,@arr_server,nil,0)
    cmd= @cmd_stack.shift
    @server.puts  cmd
    @timeout.restart
    $server_ready=false
    $console.display_ready(false)
  end
end

def old_add_listener(code,&callback)
  if code == 'console'
    @console_cb= callback
  else
  #debug "added listener for #{code}: #{callback}"
      @listeners[code]=[] if @listeners[code].nil?
      @listeners[code].push(callback)
    end
    callback
  end

  def old_remove_listener(code,callback)
    @listeners[code].delete(callback)
  end

  def eof?
    @server.eof?
  end
end

