require 'htmlsplit'
#####
# $Id: fillinform.rb,v 1.7 2003/01/14 13:13:15 ikebe Exp $
###
module HTML

  class FillInForm
    def initialize(html = nil)
      @html = html
      @output = ""
    end

    attr_reader :output
    alias to_s output

    def load(file)
      begin
	fp = open(file,'r')
	@html = fp.read
	fp.close
      rescue
	raise "#{$!}: #{file}"
      end
    end

    def set(html)
      @html = html
    end

    def fill(hash,target = nil)
      current_form = nil
      text_area = nil
      select_box = nil
      option_tag = nil
      HTMLSplit.new(@html).document.each do |tag|
	##
	# check <form> name
	if tag.is_a?(EndTag) and tag.name == 'form'
	  current_form = nil
	  @output << tag.to_s
	  next
	end
	if tag.is_a?(StartTag) and tag.name == 'form'
	  current_form = tag.attr['name']
	  @output << tag.to_s
	  next
	end
	if target and target != current_form
	  @output << tag.to_s
	  next
	end

	##
	# <textarea>
	if tag.is_a?(EndTag) and tag.name == 'textarea'
	  require 'cgi'
	  if hash[text_area] and hash[text_area].is_a?(Array)
	    @output << CGI.escapeHTML(hash[text_area][0])
	  elsif hash[text_area]
	    @output << CGI.escapeHTML(hash[text_area])
	  end
	  text_area = nil
	  @output << tag.to_s
	  next
	end
	if text_area and hash[text_area]
	  require 'cgi'
	  if hash[text_area].is_a?(Array)
	    @output << CGI.escapeHTML(hash[text_area][0])
	  else
	    @output << CGI.escapeHTML(hash[text_area])
	  end
	  text_area = nil
	  next
	end
	if tag.is_a?(StartTag) and tag.name == 'textarea'
	  text_area = tag.attr['name']
	  @output << tag.to_s
	  next
	end

	##
	# <select>
	if tag.is_a?(EndTag) and tag.name == 'select'
	  select_box = nil
	  @output << tag.to_s
	  next
	end

	##
	# <option> with no value attr.
	if tag.is_a?(CharacterData) and select_box and option_tag
	  if hash[select_box].is_a?(Array)
	    hash[select_box].each do |v|
	      if v == tag.to_s.chomp.strip
		option_tag.attr['selected'] = true
		break
	      end
	    end
	  elsif hash[select_box] == tag.to_s.chomp.strip
	    option_tag.attr['selected'] = true
	  end
	  @output << option_tag.to_s << tag.to_s
	  option_tag = nil
	  next
	end

	##
	# <option>
	if tag.is_a?(StartTag) and select_box and tag.name == 'option'
	  # option tag without value attr
	  unless tag.attr and tag.attr['value']
	    option_tag = StartTag.new('option')
	    option_tag.attr = tag.attr || {}	    
	    if option_tag.attr['selected']
	      # delete original 
	      option_tag.attr.delete('selected')
	    end
	    next
	  end

	  if hash[select_box].is_a?(Array)
	    chk = false
	    hash[select_box].each do |v|
	      if v == tag.attr['value']
		chk = true
	      end
	    end
	  elsif hash[select_box] == tag.attr['value']
	    tag.attr['selected'] = true
	    chk = true
	  elsif hash[select_box]
	    tag.attr.delete('selected')
	    chk = false
	  end
	  if chk
	    tag.attr['selected'] = true
	  else
	    tag.attr.delete('selected')
	  end
	  @output << tag.to_s
	  next
	end
	if tag.is_a?(StartTag) and tag.name == 'select'
	  select_box = tag.attr['name']
	  @output << tag.to_s
	  next
	end

	##
	# without forms.
	unless tag.is_a?(EmptyElementTag)
	  @output << tag.to_s
	  next
	end

	##
	# <input>
	if tag.is_a?(EmptyElementTag) and tag.name == 'input'
	  unless tag.attr
	    @output << tag.to_s
	    next
	  end

	  type = tag.attr['type'] == nil ? "" : tag.attr['type'].downcase
	  ##
	  # <input type="radio">
	  if type == 'radio'
	    if hash[tag.attr['name']].is_a?(Array)
	      hash[tag.attr['name']].each do |v|
		if v == tag.attr['value']
		  tag.attr['checked'] = true
		  break
		end
	      end
	    elsif hash[tag.attr['name']] == tag.attr['value']
	      tag.attr['checked'] = true
	    elsif hash[tag.attr['name']]
	      tag.attr.delete('checked')
	    end
	    @output << tag.to_s
	    next
	    ##
	    # <input type="checkbox">
	  elsif type == 'checkbox'

	    chk = false
	    if hash[tag.attr['name']].is_a?(Array)
	      hash[tag.attr['name']].each do |v|
		if v == tag.attr['value']
		  chk = true
		end
	      end
	    elsif hash[tag.attr['name']] == tag.attr['value']
	      tag.attr['checked'] = true
	    elsif hash[tag.attr['name']]
	      tag.attr.delete('checked')
	    end
	    # for multiple select
	    if chk
	      tag.attr['checked'] = true
	    else
	      tag.attr.delete('checked')
	    end
	    @output << tag.to_s
	    next
   	  elsif type == 'submit' or type == 'reset' or type == 'button'
   	    @output << tag.to_s
   	    next
	  else
	    ##
	    # text,hidden,password ..
	    require 'cgi'
	    if hash[tag.attr['name']].is_a?(Array) 
	      tag.attr['value'] = hash[tag.attr['name']][0]
 	      if tag.attr['value'] == nil
 		tag.attr['value'] = ''
 	      end
	      @output << tag.to_s
	      next
	    elsif hash[tag.attr['name']] 
	      tag.attr['value'] = hash[tag.attr['name']]
	      if tag.attr['value'] == nil
#		tag.attr['value'] = ''
	      end
	      @output << tag.to_s
	      next
	    else
	      @output << tag.to_s
	      next
	    end
	  end
	end
	##
	# default
	@output << tag.to_s
      end
      return @output
    end
  end
end
