



class IgscpError  <  StandardError
end

module IGSCP

  IGSCP_VERSION= 'Draft-5'
  REGEXP=/#(([\w\d]+)(?::[\w\d]+)*)((?: [\S]+)*)/

  include Debug

  def igscp_init
    @igscp_control_color= 'OFF'
    $igscp_clients= Hash.new
    $igscp_calls= Hash.new 
  end

  def IGSCP.is_command(line)
#debug line
  #  line[0] == ?#
 #    debug REGEXP.match(line)
    REGEXP.match(line)
  end

  def igscp_command(player,match)

#debug match.to_a.inspect
#debug caller

  #debug REGEXP.match(line).to_a.inspect
    str,cmd,family,params= match.to_a

    case family
    when 'CONTROL'; igscp_control(player,cmd,params.strip)
    when 'MOVE'; igscp_move(player,cmd,params.strip)
    when 'MARK','XMARK'; igscp_mark(player,cmd,params.strip)
    end
  end

  def IGSCP.family(match)
    match[2]
  end
  def IGSCP.number(match)
    match[3] =~ /^ (\d+)/
    $1
  end

  def IGSCP.info(player,match)
    str,cmd,family,params= match.to_a
    case cmd 
    when 'INFO:REQUEST:VERSION'
      send(player,'INFO:VERSION', IGSCP_VERSION)
    when 'INFO:REQUEST:CLIENT'
      send(player,'INFO:CLIENT',"RubyGo-#{$version}")
    when 'INFO:REQUEST:FEATURES'
      send(player,'INFO:FEATURES','INFO','MARK','XMARK','CONTROL')
    when 'INFO:FEATURES','INFO:VERSION','INFO:CLIENT'
      received(player,cmd,params.strip)
    end
  end

  def 	IGSCP.send(player,cmd,*params)
    str='#'+cmd
    params.each { |p| str << ' ' << p.to_s }
    if $igscp_clients.key?(player)
      $igsClient.send("tell #{player} #{str}")
    else
      ask(player,'INFO:REQUEST:FEATURES'){  |cmd,params| 
        register_player(player,params)
    #TODO verify features
        $igsClient.send("tell #{player} #{str}")
      }
    end
  end

  def IGSCP.register_player(name,features)
    unless $igscp_clients.key?(name)
      $igscp_clients[name]= features
    end
  end

  def IGSCP.to_color(code)
    case code
    when 'BLACK' ; 'B'
    when 'WHITE' ; 'W'
    when 'BOTH'  ; 'BOTH'
    end
  end

  def  igscp_control(player,cmd,params)
    case cmd
    when 'CONTROL:COLOR'
      return unless self.class == GoObserver
      number,color= params.split(' ')
      @igscp_control_color= IGSCP.to_color(color)
      show_control(color)			
      IGSCP.send(@teacher,"CONTROL:ACK #{number}")
      ready
      when 'CONTROL:REQUEST'
        return unless self.class == GoTeacher
        number,color= params.split(' ')
        if color == 'OFF'
          rec_message("#{player} give up control", 'info')
          control_off(player)
        else
          rec_message("#{player} request to play color #{color}", 'info')
        end
        else
          rec_message("received command:\n #{cmd} #{params}\n from #{player}", 'info')
        end
      end

      def igscp_move(player,cmd,params)
        number,move= params.split(' ')
   #debug cmd+' '+params
        node=SGF.new.parse_data(move)
  #debug node.props.inspect
  #TODO: verify player has color
        node.props.each_value { |move| 
#debug "#{move.ident} -> #{Grid.to_coords(move.col,move.row,@size)}"
          $igsClient.send("#{Grid.to_coords(move.col,move.row,@size)} #{number}")
        }

      end

      def igscp_mark(player,cmd,params)
        return unless self.class == GoObserver
        cmd=~/(.*):(.*)/
        fam=$1
        opt=$2

        case opt
        when 'ADD'
          node=SGF.new.parse_data(params)
          node.action(self)
#	@last_node.merge( node) if fam == 'SETUP'
        when 'REMOVE'
          if params == 'all'
            @goban.remove_tag('Graphics')
          else
            params.split(' ').each {  |p| 
              c,r,x,x= Coords.simple_to_ary(p)
              case fam
              when 'MARK','XMARK'
                @goban.delete_mark_at(c,r)
#		when 'SETUP'
#		  @goban.delete_stone_at(c,r)
              end
            }
          end
        when 'MOVE'
          param1,param2= params.split(' ')
          co,ro,x,x= Coords.simple_to_ary(param1)
          ct,rt,c2t,r2t= Coords.simple_to_ary(param2)
          case fam
          when 'MARK','XMARK'
            @goban.move_mark(co,ro,ct,rt,c2t,r2t)
#	when 'SETUP'
#	  @goban.move_stone(co,ro,ct,rt,c2t,r2t)
          end

        end

        end

        def old_igscp_mark(player,cmd,params)
          case cmd 
          when 'MARK:ADD'
            node=SGF.new.parse_data(params)
            node.action(self)
          when 'MARK:REMOVE'
            if params == 'all'
              @goban.remove_tag('Graphics')
            else
              node=SGF.new.parse_data(params)
              node.props.each_value { |prop| prop.delete_items(self) }
            end
          when 'MARK:MOVE'
            param1,param2= params.split(' ')
            regexp= /(..)\[(..(:..)*)\]/
            orig= regexp.match(param1)
            propo= Property.create(orig[1])
            propo.push(orig[2])
            target= regexp.match(param2)
            propt= Property.create(target[1])
            propt.push(target[2])
            co,ro,x,x= propo.simple_to_ary
            ct,rt,c2t,r2t= propt.simple_to_ary
#	debug "#{co},#{ro}-> #{ct},#{rt}:#{c2t},#{r2t}"
            @goban.move_mark(co,ro,ct,rt,c2t,r2t)
          end
        end

        def igscp_send_mark(klass,col,row)
          label= ( case klass.name
          when "Triangle"
            'TR'
          when "Circle"
            'CR'
          when "Rectangle"
            'SQ'
          when "Cross"
            'MA'
          end )
          coords= Coords.to_a(col,row)
          $igsClient.send("chatter #@number #MARK:ADD #{label}[#{coords}]")
        end

        def igscp_remove_mark(col,row)
          coords= Coords.to_a(col,row)
          $igsClient.send("chatter #@number #MARK:REMOVE #{coords}")
        end

        def igscp_remove_all
          $igsClient.send("chatter #@number #MARK:REMOVE all")
        end

        def igscp_send_node(node)
          $igsClient.send("chatter #@number #MARK:ADD #{node.to_s[1..-1]}")
        end

        def IGSCP.ask(player,command, &action)
          $igscp_calls[player]= action
          $igsClient.send("tell #{player} ##{command}")

        end

        def  IGSCP.received(player,cmd,params)

          if  action= $igscp_calls[player] 
            action.call(cmd,params)
            $igscp_calls.delete(player)
          end

        end

        def igscp_send_move(col,row)

  # @goban.cursor('watch') not sure
          move="#@player_turn[#{Coords.to_a(col,row)}]"
          IGSCP.send(@teacher,'MOVE',move) 
        end



      end # module 


