
require 'tkscrollbox'

class Console
	attr_reader :quiet

  def initialize

    @top= GoWindow.new(self)
    @top.protocol('WM_DELETE_WINDOW', proc { quit })

    @top.title( TkDefaults::GUI['Console.top']['title']+$user)


    @player_menu= Menu.new
    @open_for_match= Defaults.get_default_value('open_for_match')
    @player_menu.add('checkbutton',
                     'label' => 'Open for match' , 'variable' => @open_for_match , 'offvalue' => '0' , 'onvalue' => '1',
                     'command' => proc {
      if  @open_for_match.value == '0'
        $igsClient.send('toggle open false')
        update_user('X')
      else
        $igsClient.send('toggle open true')
        if  @looking_for_match.value == '1'
          update_user('!')
        else
          update_user('')
        end
      end } )

    @looking_for_match= Defaults.get_default_value('looking_for_match')
    @player_menu.add('checkbutton',
                     'label' => 'Looking for match' , 'variable' => @looking_for_match , 'offvalue' => '0' , 'onvalue' => '1',
                     'command' => proc {
      if  @looking_for_match.value == '0'
        $igsClient.send('toggle looking false')
        if  @open_for_match.value == '1'
          update_user('')
        else
          update_user('X')
        end

      else
        $igsClient.send('toggle looking true')
        if  @open_for_match.value == '1'
          update_user('!')
        end

      end } )


    @receive_shouts= Defaults.get_default_value('receive_shouts')
    @player_menu.add('checkbutton',
                     'label' => 'Receive shouts' , 'variable' => @receive_shouts , 'offvalue' => '0' , 'onvalue' => '1',
                     'command' => proc {
      if  @receive_shouts.value == '0'
        $igsClient.send('toggle shout false')
      else
        $igsClient.send('toggle shout true')
      end } )

    @quiet= Defaults.get_default_value('quiet')
    @player_menu.add('checkbutton',
                     'label' => 'Quiet' , 'variable' => @quiet , 'offvalue' => '0' , 'onvalue' => '1',
                     'command' => proc {
      if  @quiet.value == '0'
        $igsClient.send('toggle quiet false')
      else
        $igsClient.send('toggle quiet true')
      end } )

# singlegame always 'on' on connection
    @multiple= TkVariable.new('0')
    @player_menu.add('checkbutton',
                     'label' => 'Multiple games' , 'variable' => @multiple , 'offvalue' => '0' , 'onvalue' => '1',
                     'command' => proc {
      if  @multiple.value == '0'
        $igsClient.send('toggle singlegame true')
      else
        $igsClient.send('toggle singlegame false')
      end } )

    @player_menu.add('separator')
    @player_menu.add('command','label' => 'stats','command' => proc {$igsClient.send("stats #$user")})
    @player_menu.add('command','label' => 'results','command' => proc {$igsClient.send("results #$user")})

    @player_menu.add('separator')
    @player_menu.add('command','label' => 'quit','command' => proc {quit})

#@top.help_add('command','label'=>'The console','command'=>proc { TkHtml.new("file://#{$current_path}/../help/manual.html#console") })

    @top.help_add('command','label'=>'The console','command'=>proc { TkHtml.new("file://#{$current_path}/../help/manual.html#console") })

    @top.menubar.add('cascade','menu' => @player_menu, 'label' => $user)
# @top.menubar.add('command','image'=>nil) if $platform == 'linux' or  $platform == 'sun'

	upside= TkFrame.new(@top).pack('fill'=>'x')
    @pane= HTexturedPane.new( upside,Defaults::DEFS['CommonBackground'],20,10,8,0).pack('side'=>'left','expand'=>'yes','fill'=>'x')


    b=TkButton.new(@pane,TkDefaults::GUI['Console.button.logout'].update(
                                                                         'command'=> proc {quit}))
    b.bind_balloon
    @logout= @pane.add(b)
    @state = @pane.add_image(TkDefaults::GUI['Console.image.state'])
#debug TkDefaults::GUI['Console.image.state']['balloon']
    @state.bind_balloon
#    @netperf= TkLabel.new(@pane,TkDefaults::GUI['Console.label.netperf'])



    opts=TkDefaults::GUI['Console.button.players'].update('command'=>proc {  $playerslist.open_win})
    b=TkButton.new(@pane,opts)
    @pane.add(b)
    b.bind_balloon

    opts=TkDefaults::GUI['Console.button.games'].update('command'=>proc { $gameslist.open_win })
    b=TkButton.new(@pane,opts)
    @pane.add(b)
    b.bind_balloon

	opts=TkDefaults::GUI['Console.button.reviews'].update('command'=>proc {  $wlist.open_win})
    b=TkButton.new(@pane,opts)
    @pane.add(b)
    b.bind_balloon


    @stored= TkScrollbox.new(upside,'height'=>3).pack('side'=>'right')
	@stored.bind('<ListboxSelect>',proc {|ev|  if @stored.curselection[0] 
												send_command('load '+@stored.get(@stored.curselection[0]))
												@stored.selection_clear('active')
												 end })
    @stored_closed=false

    @pane.reconfigure

    @dialog = Dialog.new(@top, 'Console').pack('fill'=> 'both','expand'=>'yes')
    cmds=CmdLine.new(@top, proc  { |cmd| send_command(cmd) }).pack('fill'=> 'x','expand'=>'no')

    @info = TkLabel.new(@top,TkDefaults::GUI['Console.label.netperf'])
    @info.pack('side'=> 'bottom','expand'=>'no','fill'=>'x')
    @netperf= TkLabel.new(@info,TkDefaults::GUI['Console.label.netperf']).pack('side'=>'left','expand'=>'yes','fill'=>'x')
    @user_state= TkLabel.new(@info,TkDefaults::GUI['Console.label.user_state']).pack('side'=>'right')


    @list_commands = {}

    load File.join($current_path, 'scripts.rb')

    make_bindings(cmds)
    display_ready( true) if $server_ready

    if  @open_for_match.value == '0'
      update_user('X')
    elsif  @looking_for_match.value == '1'
      update_user('!')
    else
      update_user('')
    end



  end

  def update_user(state)
    case  state
    when '!'
      set_user_state('looking')
      @open_for_match.value='1'
      @looking_for_match.value='1'
    when 'X'
      @open_for_match.value='0'
      set_user_state('no_match')
    when '?'
      set_user_state('unknown')
    else
      set_user_state('free')
      @open_for_match.value='1'
      @looking_for_match.value='0'
    end

  end

  def set_user_state(image)
 #  if $platform == 'linux' or $platform == 'sun'
 #    @top.menubar.entryconfigure(3,'image'=> Defaults::ICONS[image])
 #  end
    @user_state.configure('image'=>Defaults::ICONS[image]) if image

  end

  def set_netperf(nb)
#  @netperf.configure('text'=> format("  network: %5d B/s  ",rate))
    t= Time.now
    t.gmtime
    t+=32400
    @netperf.configure('text'=> t.asctime)

  end

  def set_netlag(time)
#debug time if time>0
    @netlag.configure('text'=> "netlag: #{time/1000.0} s")
  end

  def set_net_current(bytes,time)

    @netperf.configure('text'=> format("%6db in %2.2fs",bytes, time))
  end

#def console_init_session
#init_session
#end

  def display_ready(server_ready)

    if server_ready
      @state.configure('image'=>Defaults::ICONS['ready'])
    else
      @state.configure('image'=>Defaults::ICONS['update'])
    end
    Tk.update
  end


  def register_command ( cmd, action)
    @list_commands[cmd] = action
  end

  def quit
    begin
      unless $igsClient.nil?
        $stdout.puts "Console: closing connection with IGS"
        $igsClient.close
        $igsClient= nil
      end
  #Defaults.save_entry
      $gameslist.quit if $gameslist
      $playerslist.quit if $playerslist
      $wlist.quit if $wlist
      $chatobserver.close_all if $chatobserver
      $gameslist= nil
      $playerslist= nil
      $chatobserver= nil
      $gamesobserver.close_all if $gamesobserver
      $gamesobserver=nil
#  TkDefaults.save_top_options(self,@top)
    rescue
    end
    @top.destroy
    $console=nil
  end

  def send_command(cmd)
    words=cmd.split(' ')
     # debug words
    @dialog.putline(cmd+"\n",'user_cmd')
    if @list_commands.include?(words[0])
      @list_commands[words[0]].call(*words[1..-1])
    else
      $igsClient.send(cmd) if $igsClient
    end
  end


  def putline(*args)
    @dialog.putline(*args)
  end

   #9 Match[19x19] in 15 minutes requested with TON as Black.
   #9 Use <match TON W 19 15 10> or <decline TON> to respond.
   #5 There is a dispute regarding your match:
   #5   diabolicum wants White on a 9x9 in 1 mins (10 byoyomi).
   #5   satanas wants Black on a 9x9 in 10 mins (10 byoyomi).
   #diabolicum wants a match with you:
   #diabolicum wants 19x19 in 90 minutes with 10 byo-yomi and 25 byo-stones
   #To accept match type 'automatch diabolicum'

  def parse_match(line)
    if  line =~ /Use <(.+)> or <(.+)> to respond./
      v =  /match (\S+) (W|B) (\d+) (\d+) (\d+)/.match $1
      return if v.nil?
      vars = v.to_a
      vars[6] = '25'
      if notes= Defaults::NOTES[vars[1]] and notes['decline'] == '1'
        send_command('decline ' + vars[1])
      else
        rank = $playerslist.get_user_rank(vars[1])
        m = GoMatch.new("match with #{vars[1]} #{rank}",vars)
      end
    elsif line =~ /(\S+) wants (White|Black) on a (\d+)x\d+ in (\d+) mins \((\d+) byoyomi\)./
      if $1 == $user
        return
      else
        color = ($2 == 'White' ? 'B' : 'W')
      end
      rank = $playerslist.get_user_rank($1)
      m = GoMatch.new("#{$1} #{rank}  wants:",[nil,$1,color,$3,$4,$5,'25'])
    elsif line =~ /(\S+) wants (\d+)x\d+ in (\d+) minutes with (\d+) byo-yomi and (\d+) byo-stones/
      rank = $playerslist.get_user_rank($1)
      m = GoMatch.new("#{$1} #{rank}  wants:",[nil,$1,nil,$2,$3,$4,$5]) if $1 != $user
    end
  end


  def receive(code,line)
    tag = Defaults.console_show(code,line)
    if tag
      @dialog.putline(line+"\n",tag)
    end

    case code
    when IGSProtocol::AUTOASK
      parse_match(line)
    when IGSProtocol::INFO
      parse_match(line)
    when IGSProtocol::ERROR
      parse_match(line)
    when IGSProtocol::SAVED
     add_stored(line)
    end

    make_vars(code,line)

  end

  def add_stored(line)
    if @stored_closed 
		@stored.delete(0,'end')
		@stored_closed= false
	end
	if line =~ /Found/
		@stored_closed= true
	else
		line.split(' ').each { | gm|
			@stored.insert('end',gm) unless gm.empty?
		}
	end
		
  end


end



