=begin
= WebUnit::Param/...
  Copyright(C) 2001 yuichi TAKAHASHI, Narushima Hironori.
  $Id: params.rb,v 1.1.1.1 2003/01/21 11:50:40 yuichi Exp $
=end

module WebUnit

  class Param < HtmlElem

    attr_reader :name, :type, :relations
    attr_accessor :stat, :value

    def initialize( tag, ah )
      super
      @type = ah["type"] ? ah["type"] : 'text'
      @value = ah["value"]
      @relations = []
      @stat = ah.key?( 'checked' ) ? 'on' : 'off'
    end

    def update( p )
      @relations << p
    end

    def query_data
      value = @value ? CGI::escape( @value ) : ''
      @name ? ( CGI::escape( @name ) + '=' + value ) : nil
    end

    def multipart_query_data( boundary)
      value = @value ? @value : ''
      
      if (@name)
        name = CGI::escape(@name)
          "--#{boundary}\n" +
          %!Content-Disposition: form-data; name="#{name}"\n! +
          "\n" +
          value + "\n"
      else
        nil
      end
    end
  end

  class Input < Param

    def initialize( ah )
      super( 'input', ah )
    end
    
    def on
      @stat = 'on'
    end

    def off
      @stat = 'off'
    end

    def inspect
      a = super + "[stat:#{@stat}]"
    end

  end

  class InputRadio < Input

    def on
      @stat = 'on'
      @relations.each do |r|
        r.off
      end
    end

    def query_data
      value = @value ? CGI::escape( @value ) : ''
      (@stat == 'on' and @name) ? CGI::escape(@name) + '=' + value : nil
    end

    def multipart_query_data( boundary)
      if @stat == 'on'
        super(boundary)
      else
        nil
      end
    end

    def value=( v )
      self.stat = self.value == v ? 'on' : 'off'
      @relations.each do |e|
        e.stat = e.value == v ? 'on' : 'off'
      end
    end
  end

  class InputCheckbox < Input
    def query_data
      value = @value ? CGI::escape( @value ) : 'on'
      (@stat == 'on' and @name) ? @name + '=' + value : nil
    end

    def multipart_query_data( boundary)
      if @stat == 'on'
        super( boundary)
      else
        nil
      end
    end
  end

  class InputSubmit < Input
    def query_data
      value = CGI::escape( @value ? @value : 'Submit Query' )
      @name ? CGI::escape(@name) + '=' + value : nil
    end
  end

  class InputImage < Input
    attr_writer :x, :y

    def query_data
      @name + '.x=' + @x.to_s + '&' + @name + '.y=' + @y.to_s
    end
    
    def multipart_query_data( boundary)
      "--#{boundary}\n" +
      %!Content-Disposition: form-data; name="#{@name}.x"\n! +
      "\n" +
      @x.to_s + "\n" +
      "--#{boundary}\n" +
      %!Content-Disposition: form-data; name="#{@name}.y"\n! +
      "\n" +
      @y.to_s + "\n"
    end
  end

  class InputReset < Input

    def query_data
      nil
    end

    def multipart_query_data( boundary)
      nil
    end
    
  end

  class Select < Param

    attr_reader :options

    def initialize( ah )
      super( 'select', ah )
      @options = []
      @size = ah["size"]
      @type = 'select'
    end

    def add_option( option )
      @options.push( option )
    end

    def end_option
      if @size == nil && @options.reject { |o| o.stat == 'off' } == []
        @options[0].select
      end
    end

    def select( arr )
      @options.each do |o|
        o.deselect
      end
      arr.each do |e|
        @options[e].select if e.kind_of?( Integer )
        if e.kind_of?( String )
          @options.each do |o|
            o.select if o.value == e || o.data == e
          end
        end
      end
    end

    def query_data
      a = []
      @options.each do |o|
        a << o.query_data( @name )
      end
      s = a.compact.join('&')
      s == '' ? nil : s
    end

    def multipart_query_data( boundary)
      lines = ''
      @options.each do |o|
        data = o.multipart_query_data(boundary, @name)
        lines << data if data
      end
      
      lines
    end

    def value
      arr = []
      @options.each do |o|
        arr << o.value if o.stat == 'on'
      end
      case arr.size
        when 0 then nil
        when 1 then arr[0]
        else arr
      end
    end

    def value= ( v )
      @options.each do |o|
        if o.value == v
          o.select
        else
          o.deselect
        end
      end
    end
  end

  class SelectOption < HtmlElem
    attr_reader :stat

    def initialize( ah )
      super( 'option', ah )
      @value = ah["value"]
      @stat = ah.key?( 'selected' ) ? 'on' : 'off'
      @type = 'option'
    end

    def value
      @value ? @value : @data
    end

    def select
      @stat = 'on'
    end

    def deselect
      @stat = 'off'
    end

    def query_data( name )
      @value = @data unless @value
      value = @value ? CGI::escape( @value ) : ''
      (@stat == 'on' and name) ? name + '=' + value : nil
    end
    
    def multipart_query_data( boundary, name)
      @value = @data unless @value
      value = @value ? @value : ''
      
      if @stat == 'on' and name
        "--#{boundary}\n" +
        %!Content-Disposition: form-data; name="#{CGI::escape(name)}"\n! +
        "\n" +
        value + "\n"
      else
        nil
      end
    end
    
  end

  class Textarea < Param
    def initialize( ah )
      super( 'textarea', ah )
      @type = 'textarea'
    end

    def value
      @value ? @value : @data
    end

    def query_data
      val = @value ? @value : @data
      value = val ? CGI::escape( val ) : ''
      @name ? ( CGI::escape( @name ) + '=' + value ) : nil
    end
                          
    def multipart_query_data( boundary)
      @value = @data unless @value
      value = @value ? @value : ''

      if @name
        "--#{boundary}\n" +
        %!Content-Disposition: form-data; name="#{CGI::escape(@name)}"\n! +
        "\n" +
        value + "\n"
      else
        nil
      end
    end
    
  end
  
  class InputFile < Input
    def query_data
      nil
    end

    def multipart_query_data( boundary)
      if @name and @value
        "--#{boundary}\n" +
        %!Content-Disposition: form-data; name="#{File.basename(@name)}"; filename="#{File.basename(@value)}"\n! +
        "Content-Type: text/plain\n" +
        "\n" +
        IO.readlines(@value).join('') + "\n"
      else
        nil
      end
    end
  
  end

end
