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

module Qwik
  class Action
    def backtrace_html(e)
      host = @req.fromhost
      if host == "localhost" || host == "127.0.0.1"
	return PrettyBacktrace.new.to_html(e)
      end
    end

    def plg__qwik_test_for_raise_exception # for demonstration
      no_such_local_variable
    end
  end

  class PrettyBacktrace
    def initialize
      @pos_num = 3
      @margin = 10
      @min_margin = -1
    end

    def to_html(e)
      margin = @margin
      trs = e.backtrace.map {|str|
	sf, sl, method = str.split(":", 3)
	margin -= 1
	[[:tr,
	    [:td, {:class=>"file"}, get_pos(sf, sl)+":", [:strong, sl]],
	    [:td, {:class=>"method"}, method.to_s]],
	  [:tr,
	    [:td, {:class=>"excerpt", :colspan=>"3"},
	      get_excerpt(sf, sl.to_i, margin)]]]
      }
      [[:h3, e.to_s], [:table, {:class=>"exception"}, trs]]
    end

    def get_pos(sourcefile, sourceline)
      ar = sourcefile.split("/")
      ar = ar[-@pos_num, @pos_num] if @pos_num < ar.length
      ar.join("/")
    end

    def get_excerpt(file, linenum, margin)
      margin = @min_margin if margin < @min_margin
      return "" if margin < 0
      f = file.path
      return "" unless f.exist?
      str = f.read
      b = linenum - margin - 1 # beginning
      ar = str.to_a[b, margin*2+1]

      table = []
      ar.each_with_index {|line, num|
	line = " \n" if line == "\n" # only for visual effect
	n = b + num + 1
	attr = {:class=>"even"}
	attr = {:class=>"odd"} if n % 2 == 1
	attr = {:class=>"target"} if n == linenum
	table << [:tr, attr, [:th, n.to_s], [:td, [:pre, line]]]
      }
      [:table, table]
    end
  end
end

if $0 == __FILE__
  $LOAD_PATH << "../../lib" unless $LOAD_PATH.include?("../../lib")
  require "t/test"
  $debug = true
end

if $debug
  class TC_ActException < Test::Unit::TestCase
    include TestSession

    def test_exception_html
      t_add_user
      page = @site.create_new

      page.store("{{nosuch}}")
      session("/test/1.html")
      assert_equal([:div, {:class=>"section"}, ["nosuch plugin"]],
		   @res.body.get_path("//div[@class='section']"))
      assert_xml("nosuch plugin", "//div[@class='section']")

      @config.test = false

      page.store("{{_qwik_test_for_raise_exception}}")
      session("/test/1.html")
      assert_text(/\Aundefined local variable or method `no_such_local_variable' for #<Qwik::Action:/, "h3")

      @config.test = true
    end
  end
end
