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

$LOAD_PATH << "../../lib" unless $LOAD_PATH.include?("../../lib")
require "test/unit"
require "qwik/test-module-path"
require "qwik/request"
require "qwik/response"
require "qwik/loadlib"
#require "qwik/memory"
require "webrick/log"

module TestSession
  include ModulePath

  DEFAULT_USER = "user@e.com"

  def setup
    web_setup
  end

  def web_setup
    # setup config
    if !defined?($test_config)
      config = Qwik::Config.new(true)
      config.test = true	# do not send mail
      config.pass_file = "./password.txt"
      $test_org_data_dir = config.data_dir.dup
      config.data_dir = "."
      $test_config = config
    end
    @config = $test_config
    @org_data_dir = $test_org_data_dir

    # setup memory
    if !defined?($test_memory)
      memory = Qwik::ServerMemory.new(@config)
      logfile = "testlog.txt"
      loglevel = WEBrick::Log::INFO
      logger = WEBrick::Log::new(logfile, loglevel)
      memory[:logger] = logger
      $test_memory = memory
    end
    @memory = $test_memory

    # setup dir
    @wwwdir = "./www/".path
    @wwwdir.setup
    @dir = "./test/".path
    @dir.setup

    # setup site
    @site = @memory.farm.get_site("test")
  end

  def teardown
    web_teardown
  end

  def web_teardown
    @site.erase_all if @site
    @wwwdir.teardown if @wwwdir
    @dir.teardown if @dir
  end

  def t_site_open
    page = @site["_SiteConfig"]
    page.store(":open:true")
  end

  def t_add_user(user = DEFAULT_USER)
    @site.member.add(user) unless @site.member.exist?(user)
  end

  def t_setup_user(req, user)
    req.cookies["user"] = user
    gen = @memory.passgen
    req.cookies["pass"] = gen.generate(user)
  end

  def session(path = "/test/")
    # setup_req
    req = Qwik::Request.new(@config)

    # setup user
    t_setup_user(req, DEFAULT_USER)

    req.parse_host("example.com")

    if /\APOST / =~ path
      req.instance_eval {
	@request_method = "POST"
      }
      path.sub!(/\APOST /, "")
    end

    if path.include?("?")
      path, query_str = path.split("?", 2)
      query = WEBrick::HTTPUtils.parse_query(query_str)
      req.query.clear
      req.query.update(query)
    end

    req.parse_path(path)
    req.accept_language = ["en"]
    req.instance_eval {
      @fromhost = "localhost"
    }

    # setup_res
    res = Qwik::Response.new(@config)
    res.make_mimetypes(WEBrick::HTTPUtils::DefaultMimeTypes)

    # setup_action
    @action = Qwik::Action.new(@config, @memory, req, res)
    site = @site
    @action.instance_eval {
      @site = site;
    }

    yield(req) if block_given?

    action = Qwik::Action.new(@config, @memory, req, res)
    action.run

    dummy_str = res.setback_body(res.body)

    @res = res
    return res # not @res, since @res is not thread safe.
  end

  # ------------------------------ assert xpath module
  # xpath related.
  def assert_path(e, w,
		  user=DEFAULT_USER, path="//div[@class='section']", &b)
    if user
      t_add_user
    else
      t_site_open
    end
    page = @site["1"]
    page = @site.create_new if page.nil?
    page.store(w)
    res = session("/test/#{page.key}.html") {|req|
      yield(req) if block_given?
      t_setup_user(req, user)
    }
    div = res.body.get_path(path)

    if e.is_a? Array
      s = div.inside.remove_comment.get_single
      return assert_equal(e, s)
    end

    s = div.inside.rb_format_xml(-1, -1).chomp
    assert_equal_or_match(e, s)
  end

  def assert_wiki(e, w, user=DEFAULT_USER, &b)
    assert_path(e, w, user, "//div[@class='section']", &b)
  end

  def pw(xpath=nil, res=@res) # show by xpath, using wabisabi
    w = res.body.get_path(xpath)
    if w.nil?
      puts "nil"
      return
    end
    pp w
  end

  # ------------------------------ assert module
  def assert_equal_or_match(e, s)
    return assert_match(e, s) if e.is_a? Regexp
    assert_equal(e, s)
  end

  def assert_xpath(e, path, res=@res)
    elem = res.body.get_path(path)
    return assert_equal(e, nil) if elem.nil?
    assert_equal(e, elem)
  end

  def assert_in(e, path, res=@res)
    elem = res.body.get_path(path)
    return assert_equal(e, nil) if elem.nil?
    elem = elem.inside.get_single
    assert_equal(e, elem)
  end

  def assert_text(e, tag, res=@res)
    elem = res.body.get_tag(tag)
    return assert_equal(e, nil) if elem.nil?
    assert_equal_or_match(e, elem.text)
  end

  def assert_attr(e, tag, res=@res)
    elem = res.body.get_tag(tag)
    return assert_equal(e, nil) if elem.nil?
    assert_equal(e, elem.attributes_str)
  end

  def assert_xml(e, xpath, res=@res)
    elem = res.body.get_path(xpath)
    return assert_equal(e, nil) if elem.nil?

    s = elem.inside
    return assert_equal(e, nil) if s.nil?

    if e.is_a? Array
      s = s.get_single
      return assert_equal(e, s)
    end

    if s.is_a? Array
      s = s.format_xml
    else
      s = s.to_s
    end
    assert_equal_or_match(e, s)
  end

  def assert_rattr(e, xpath, res=@res)
    elem = res.body.get_path(xpath)
    return assert_equal(e, nil) if elem.nil?
    attr = elem.get_attr
    return assert_equal(e, nil) if attr.nil?
    attr = hash_to_str(attr)
    assert_equal(e, attr)
  end

  def hash_to_str(src)
    h = {}
    src.each {|k, v|
      k = k.to_s
      next if k == "xmlns"
      h[k] = v.to_s
    }
    h
  end
  private :hash_to_str
end

# ============================== test functions
def load_files(base)
  Dir.glob(base+"-*.rb") {|filename|
    require filename
  }
end

def load_by_loadlib(arg)
  loadlib = Qwik::LoadLibrary.new
  loadlib.glob("../../lib", arg)
end

def load_basic_test
  #load_files("test")
  #load_files("act")

  load_by_loadlib("qwik/test-module-*.rb")
  load_by_loadlib("qwik/ml-*.rb")
  load_by_loadlib("qwik/test-ml-*.rb")
  load_by_loadlib("qwik/test-submit-*.rb")
  load_by_loadlib("qwik/act-*.rb")

  #load_files("ext")
end

def load_extra_test
  #load_files("check")
  #load_by_loadlib("qwik/*.rb")

end

def load_benchmark
  load_files("bench")
end
