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

$LOAD_PATH << "../../lib" unless $LOAD_PATH.include?("../../lib")

module Qwik
  class Action
    CALC_INT_RE   = /\A[0-9,]+\z/
    CALC_FLOAT_RE = /\A[0-9,.]+\z/

    def calc_parse_num(str)
      return [nil, 0, nil] if str.empty?
      return [nil, nil, nil] if /\A[^0-9]+\z/ =~ str # no number

      prefix = suffix = nil

      if /\A([^-0-9]+)[0-9]/ =~ str
	prefix = $1
	str = str.sub($1, "")
      end

      if /[0-9]([^0-9]+)\z/ =~ str
	suffix = $1
	str = str.sub($1, "")
      end

      i = str.to_i
      f = str.to_f
      n = (f-i) == 0 ? i : f
      return [prefix, n, suffix]
    end

    def plg_calc
      str = yield

      tokenizer = TextTokenizer.new
      tokens = tokenizer.tokenize(str)

      table = []
      sum = []

      used_prefix = []
      used_suffix = []

      tokens.each {|token|
	case token[0]
	when :table
	  col = []
	  token[1..-1].each_with_index {|t, i|
	    prefix, n, suffix = calc_parse_num(t)
	    col << t
	    if n
	      sum[i] ||= 0
	      if sum[i] != :NaN
		sum[i] += n
	      end

	      if prefix
		if used_prefix[i].nil?
		  used_prefix[i] = prefix
		end
	      end

	      if suffix
		if used_suffix[i].nil?
		  used_suffix[i] = suffix
		end
	      end

	    else
	      sum[i] = :NaN
	    end
	  }
	  table << col
	else
	  return "you can use only tables in calc plugin"
	end
      }

      #qp sum

      if 0 < sum.length
	sum_str = []
	sum.each_with_index {|s, i|
	  if s == :NaN
	    sum_str << ""
	  else
	    sum_str << [used_prefix[i], s.to_s, used_suffix[i]].join
	  end
	}
	#qp sum_str
	tokens << [:table, *sum_str]
      end

      parser = TextParser.new
      tree = parser.make_tree(tokens)

      table = tree[0]
      last_tr = table.last
      last_tr.insert(1, {:class=>"sum"})

#      last_tr[2..-1].each {|td|
#	td[0] = :th if td[0] == :td
#      }

      return tree
    end
  end
end

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

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

    def test_all
      session

      # test calc_parse_num
      assert_equal([nil, 0,   nil], @action.calc_parse_num(""))
      assert_equal([nil, nil, nil], @action.calc_parse_num("a"))
      assert_equal([nil, 1,   nil], @action.calc_parse_num("1"))
      assert_equal([nil, 1.5, nil], @action.calc_parse_num("1.5"))
      assert_equal([nil, 1,  "MB"], @action.calc_parse_num("1MB"))
      assert_equal([nil, 1.5,"MB"], @action.calc_parse_num("1.5MB"))
      assert_equal(["$", 1,   nil], @action.calc_parse_num("$1"))
      assert_equal(["$", 1.5, nil], @action.calc_parse_num("$1.5"))

      # test plg_calc
      assert_wiki([:table, [:tr, [:td, "0"]],
		    [:tr, {:class=>"sum"}, [:td, "0"]]],
		  "{{calc\n,0\n}}")
      assert_wiki([:table, [:tr, [:td, "1"]], [:tr, [:td, "2"]],
		    [:tr, {:class=>"sum"}, [:td, "3"]]], "{{calc\n,1\n,2\n}}")
      assert_wiki([:table,
		    [:tr, [:td, "1"], [:td, "3.4"]],
		    [:tr, [:td, "2"], [:td, "5.6"]],
		    [:tr, {:class=>"sum"}, [:td, "3"], [:td, "9.0"]]],
		  "{{calc\n,1,3.4\n,2,5.6\n}}")
      assert_wiki([:table, [:tr, [:td, "a"], [:td, "0"]],
		    [:tr, {:class=>"sum"}, [:td, ""], [:td, "0"]]],
		  "{{calc\n,a,0\n}}")
      assert_wiki([:table, [:tr, [:td, "1MB"]],
		    [:tr, {:class=>"sum"}, [:td, "1MB"]]],
		  "{{calc\n,1MB\n}}")
      assert_wiki([:table, [:tr, [:td, "$1"]],
		    [:tr, {:class=>"sum"}, [:td, "$1"]]],
		  "{{calc\n,$1\n}}")
      assert_wiki([:table, [:tr, [:td, "$1"]],
		    [:tr, {:class=>"sum"}, [:td, "$1"]]],
		  "{{calc\n,$1,\n}}")
      assert_wiki([:table,
		    [:tr, [:td, "$100"], [:td, "CPU"]],
		    [:tr, [:td, "$100"], [:td, "Memory"]],
		    [:tr, [:td, "$20.5"], [:td, "Cable"]],
		    [:tr, [:td, "$250"], [:td, "Graphic Card"]],
		    [:tr, [:td, "$250"], [:td, "HDD"]],
		    [:tr, [:td, "$400"], [:td, "Mother Board"]],
		    [:tr, {:class=>"sum"}, [:td, "$1120.5"], [:td, ""]]],
		  "{{calc
,$100	,CPU
,$100	,Memory
,$20.5	,Cable
,$250	,Graphic Card
,$250	,HDD
,$400	,Mother Board
}}")
      assert_wiki([:table,
		    [:tr, [:td, "1–œ"], [:td, "CPU"]],
		    [:tr, [:td, "1–œ"], [:td, "Memory"]],
		    [:tr, [:td, "0.2–œ"], [:td, "Adapter"]],
		    [:tr, [:td, "2.5–œ"], [:td, "nVidia"]],
		    [:tr, [:td, "2.5–œ"], [:td, "HDD 250GB"]],
		    [:tr, [:td, "4–œ"], [:td, "NAS"]],
		    [:tr, [:td, "22–œ"], [:td, "ThinkPad X40"]],
		    [:tr, {:class=>"sum"}, [:td, "33.2–œ"], [:td, ""]]],
		  "{{calc
,1–œ,	CPU
,1–œ,	Memory
,0.2–œ,	Adapter
,2.5–œ,	nVidia
,2.5–œ,	HDD 250GB
,4–œ,	NAS
,22–œ,	ThinkPad X40
}}")
    end
  end
end
