# Copyright (C) 2003-2005 Kouichirou Eto, All rights reserved.

$LOAD_PATH.unshift("../../compat") unless $LOAD_PATH.include?("../../compat")
require "htree"
$LOAD_PATH << "../../lib" unless $LOAD_PATH.include?("../../lib")

module HTree
  module GeneratorModule
    def method_missing(symbol, *args, &block)
      make(symbol, *args, &block)
    end

    def p(*args, &block)
      make(:p, *args, &block)
    end

    def make(symbol, *args, &block)
      ar = make_ar(symbol, *args, &block)
      Elem.new(*ar)
    end

    def make_ar(symbol, *args, &block)
      ar = []

      ar << symbol.to_s.gsub(/_/, "-") # tag name

      if 0 < args.length
	a = add_args(args)
	ar += a
      end

      if block
	y = block.call
	ar += add_elems(y)
      end

      ar
    end

    def add_args(args)
      args.flatten.map {|arg|
	symbol_to_hash(arg)
      }
    end

    def add_elems(args)
      return [] if args.nil?
      return [args] unless args.kind_of? Array
      ar = []
      args.each {|a|
	next if a.nil?
	ar << a
      }
      ar = [""] if ar.empty?
      ar
    end

    def symbol_to_hash(s)
      h = {}
      s.each {|k, v|
	next if v.nil?
	h[k.to_s] = v.to_s
      }
      h
    end
  end

  class Generator; include GeneratorModule; end
end

if $0 == __FILE__
  require "test/unit"
  require "qwik/htree-format-xml"
  $debug = true
end

if $debug
  class TC_HTreeGenerator < Test::Unit::TestCase
    def assert(e, s)
      assert_equal(e, s.format_xml)
    end

    def test_all
      @g = HTree::Generator.new

      # test_htree_generator
      assert("<p/>", @g.p)
      doc = HTree::Doc.new(@g.p)
      assert("<p/>", doc)
      str = ""
      doc.display_xml(str)
      assert_equal("<p\n/>", str)

      assert("<a/>", @g.a)
      assert("<b/>", @g.b{})
      assert("<b></b>", @g.b{""})
      assert('<img src="u"/>', @g.img(:src=>"u"))
      assert("<b>t</b>", @g.b{"t"})
      assert("<p><b>b</b></p>", @g.p{@g.b{"b"}})
      assert("<p>t<p>b</p>t</p>", @g.p{["t", @g.p{"b"}, "t"]})
      assert('<a href="u">t</a>', @g.a(:href=>"u"){"t"})
      assert('<font size="7">t</font>', @g.font(:size => 7){'t'})

      # test_namespace
      assert("<b>t</b>", @g.make("b"){"t"})
      assert("<n:b>t</n:b>", @g.make("n:b"){"t"})
      assert('<a href="u">t</a>', @g.make("a", :href=>"u"){"t"})

      html = @g.html {[
	  @g.head {[
	      @g.title {"タイトル"},
	    ]},
	  @g.body {[
	      @g.pre {[@g.b {"world"},  "hello"]},
	      @g.pre {["This is ", @g.b{"bold"}, " text."]},
	      @g.pre {["This is ", @g.i{"italic"}, " text."]},
	      @g.p {["This is ", @g.a(:href=>"hoge"){"anchor"}, " text."]},
	    ]}
	]}
      assert("<html><head><title>タイトル</title></head><body><pre><b>world</b>hello</pre><pre>This is <b>bold</b> text.</pre><pre>This is <i>italic</i> text.</pre><p>This is <a href=\"hoge\">anchor</a> text.</p></body></html>", html)

      # test_with_underbar
      assert("<ab/>", @g.ab)
      assert("<a-b/>", @g.a_b)
      assert("<a-b/>", @g.make("a_b"))
      assert("<a-b/>", @g.make("a-b"))

      # test_ordered_hash
      assert("<a b=\"c\"/>", @g.a({"b"=>"c"}))
      assert("<a b=\"c\"/>", @g.a([{"b"=>"c"}]))
      assert("<a b=\"c\" d=\"e\"/>", @g.a([{"b"=>"c"}, {"d"=>"e"}]))
      assert("<a b=\"c\" d=\"e\"/>", @g.a({"b"=>"c"}, {"d"=>"e"}))

      # test_multi_attr
      assert("<a href=\"h\" class=\"c\"/>",
	     @g.make("a", {:href=>"h"}, {:class=>"c"}))
      assert("<a class=\"c\" href=\"h\"/>",
	     @g.make("a", {:class=>"c"}, {:href=>"h"}))
    end
  end
end
