if ENV['COVERAGE'] then
  $stderr.puts "Loading coverage library"
  require 'rubygems'
  require 'coverage'
end

require 'test/unit'
require 'latex/parser'

class Array
  def firsts
    map { |a,b| a }
  end
end

class TestLatexParser < Test::Unit::TestCase
  include LaTeX
  
  def setup
    @parser = LaTeX::Parser.new
    
    @begin_doc = [:BEGIN_DOCUMENT, "\\begin{document}\n"]
    @end_doc = [:END_DOCUMENT, "\\end{document}"]
  end

  def subst_words(elt)
    case elt
    when Array
      elt.map { |elt| subst_words(elt) }
    else
      if Word === elt then elt.to_s else elt end
    end
  end

  def assert_parse_equal(expected,actual)
    assert_equal expected,subst_words(actual)
  end
  
  def body_scanner
    scanner = LaTeX::Scanner.new
    scanner.start = :document
    scanner
  end
  
  def body_scan(str)
    s = body_scanner
    result = s.scan(str)
    s.check_stack
    result
  end
  
  def body_parse(tokens)
    parser = LaTeX::Parser.new
    tree = parser.parse([@begin_doc] + tokens + [@end_doc])
    tree[1][1...-1]
  end
  
  def body_parse_str(str)
    body_parse(body_scan(str))
  end
  
  def test_parts
    tree = @parser.parse([
        [:NONBODY_LINE, "asdf\n"],
        [:NONBODY_LINE, "ghij\n"],
        @begin_doc,
        [:WORD, "hello"],
        [:SPACE, "\n"],
        @end_doc,
        [:NONBODY_LINE, "klmn\n"],
        [:NONBODY_LINE, "opqr\n"]
    ])
    
    assert_equal [
        ["asdf\n", "ghij\n"], 
        [@begin_doc[1], "hello", Whitespace.create("\n"), @end_doc[1]],
        ["klmn\n", "opqr\n"]
      ], tree
  end
  
  def test_nlpar
    tree = body_parse_str("hello\n\nthere")
    assert_equal ["hello","\n\n", "there"], tree

    tree = body_parse_str("hello\n\n\nthere")
    assert_equal ["hello","\n\n\n", "there"], tree
  end

  def test_cs_bare
    tree = body_parse_str("\\somecs")
    assert_equal "\\somecs", tree.first.name
  end
  
  def test_cs_double
    tree = body_parse_str("\\somecs\\csarg")
    assert_equal "\\somecs", tree[0].name
    assert_equal [["\\csarg"]], tree[0].args
  end

  def test_cs_double_arg
    tree = body_parse_str("\\somecs\\csarg{arg}")
    assert_equal "\\somecs", tree[0].name
    assert_equal [["\\csarg"],Argument.new("{",[Word.create("arg")],"}")], tree[0].args
  end
  
  def test_cs_arg1
    tree = body_parse_str("\\somecs{argument1}")
    assert_equal [Argument.new("{",[Word.create("argument1")],"}")], tree[0].args
  end
  
  def test_cs_arg2
    tree = body_parse_str("\\somecs[optarg]{argument1}")
    assert_equal [Argument.new("[",[Word.create("optarg")],"]"),
                  Argument.new("{",[Word.create("argument1")],"}")], tree[0].args
  end
  
  def test_cs_arg_double
    tree = body_parse_str("\\somecs{argument1}\\separate")
    assert_equal 2, tree.length
    assert_equal "\\somecs", tree[0].name
    assert_equal [Argument.new("{",[Word.create("argument1")],"}")], tree[0].args
    assert_equal "\\separate", tree[1].name
  end
  
  def test_group
    tree = body_parse_str("{sometext}")
    assert_instance_of Group, tree[0]
    assert_equal ["sometext"], tree[0].content
  end
  
  def test_whitespace
    tree = body_parse_str(" ")
    assert_equal [Whitespace.create(" ")], tree

    tree = body_parse_str("\n")
    assert_equal [Whitespace.create("\n")], tree

    tree = body_parse_str("\t")
    assert_equal [Whitespace.create("\t")], tree

    tree = body_parse_str("\n\t")
    assert_equal [Whitespace.create("\n\t")], tree

    tree = body_parse_str(" \n\n")
    assert_equal [Whitespace.create(" "),"\n\n"], tree
  end
  
  def test_mismatch_env
    assert_raises LaTeX::Parser::Error do
      tree = body_parse_str("\\begin{x}\nsometext\n\\end{y}")
    end
  end
  
  def test_match_env
    tree = body_parse_str("\\begin{x}\nsometext\n\\begin{y}asdf\\end{y}\n\\end{x}")

    assert_equal 1, tree.length
    env_x = tree.first
    assert_instance_of Environment, env_x
    
    assert_equal "x", env_x.name
    assert_equal 5, env_x.content.length
    assert_equal [Whitespace.create("\n"), "sometext", Whitespace.create("\n")], env_x.content[0,3]
    assert_equal Whitespace.create("\n"), env_x.content[4]
    
    env_y = env_x.content[3]
    assert_instance_of Environment, env_y

    assert_equal "y", env_y.name
    assert_equal "asdf", env_y.content.to_s
  end

  def test_embedded_env
    assert_nothing_raised do
      tree = body_parse_str('\newenvironment{env}{\begin{foo}}{\end{foo}}')
    end
  end

  def test_word_whitespace
    w1 = LaTeX::Word.create("asdf")
    w2 = LaTeX::Word.create("asdf")
    
    assert_equal w1.object_id, w2.object_id

    ws1 = LaTeX::Whitespace.create("asdf")

    assert_instance_of LaTeX::Whitespace, ws1
    assert ws1.object_id != w1.object_id
  end

  def test_verbatim
    str = "\\begin{verbatim}\nfoo\n\\end{verbatim}\n"
    tree = body_parse_str(str)
    assert_instance_of LaTeX::Environment, tree[0]
    assert_equal str, tree.to_s 
  end

  def test_amp
    str = "hello & there"
    tree = body_parse_str(str)
    assert_instance_of LaTeX::StandalonePunctuation, tree[2]
    assert !tree[2].atomic?
  end
  
  def test_skip
    str = '\vskip 1 em'
    tree = body_parse_str(str)
    assert_instance_of LaTeX::ControlSequence, tree[0]
    assert_equal str, tree[0].name
  end
  
end
