#!/usr/local/bin

require 'xtemplate'

info = {
  'template' => {'filename' => '', 'mtime' => ''},
  'data'     => {'filename' => '', 'mtime' => ''},
}

$out      = $stdout
$filename = nil
$data     = {}
xml_data = nil
yaml_data= nil

$debug = false
$eruby = false
$erb   = false
$show_time = false
$dump  = false
$template = nil
$plugin = nil

# for amrita
$use_amrita = false
$use_compiler = false
$hint = nil


$eruby = Object.new
def $eruby.print(*msg)
  @str.concat(*msg)
end
def $eruby.run(code)
  @str = ""
  if( $eruby )
    eval(ERuby::Compiler.new().compile_string(code))
  elsif( $erb )
    eval(ERB::Compiler.new(nil).compile(code))
  end
  $plugin ||= @plugin
  @str
end

if( $eruby = ARGV.index("--with-eruby") )
  require 'eruby'
  ARGV.delete_at($eruby)
elsif( $erb = ARGV.index("--with-erb") )
  require 'erb'
  ARGV.delete_at($erb)
end
if( $debug = ARGV.index("--debug") )
  ARGV.delete_at($debug)
end

while ARGV[0]
  case ARGV[0]
  when "--use-amrita"
    $use_amrita = true
  when "--use-compiler"
    $use_compiler = true
  when "--hint"
    ARGV.shift
    $hint = ARGV[0]
    $hint = eval($hint)
  when "--show-time"
    $show_time = true
#  when "--html"
#    $html = true
  when "-x"
    ARGV.shift
    xml_data = File.open(ARGV[0])
    if( $eruby || $erb )
      xml_data = obj.run(xml_data.read)
      if( $debug )
	print(xml_data, "\n")
      end
    end
    $data = XTemplate::XMLDocument.new(xml_data)
    info['data']['filename'] = ARGV[0]
    info['data']['mtime']    = File.mtime(ARGV[0]).to_s
  when "-d"
    ARGV.shift
    $data = File.open(ARGV[0]){|f| f.read}
    $data = eval($data)
    info['data']['filename'] = ARGV[0]
    info['data']['mtime']    = File.mtime(ARGV[0]).to_s
  when "-y"
    ARGV.shift
    yaml_data = File.open(ARGV[0]){|f| f.read}
    begin
      require 'xtemplate/yaml'
    rescue LoadError
      $stderr.print("YAML library (http://yaml4r.sourceforge.net/) is not installed.\n")
      exit(1)
    end
    $data = XTemplate::YAMLDocument.new(yaml_data)
    info['data']['filename'] = ARGV[0]
    info['data']['mtime']    = File.mtime(ARGV[0]).to_s
  when "-D"
    ARGV.shift
    $data = eval(ARGV[0])
    info['data']['filename'] = '-'
    info['data']['mtime']    = Time.now.to_s
  when "-c"
    ARGV.shift
    $filename = ARGV[0]
    $dump = true
  when "-T"
    ARGV.shift
    $filename = ARGV[0]
    $template = File.open(ARGV[0]){|f| f.read}
  when "-t"
    ARGV.shift
    $filename = ARGV[0]
    if( $eruby || $erb )
      $text = obj.run(File.open($filename){|f|f.read})
      if( $debug )
	print($text, "\n")
      end
    end
  when "-o"
    ARGV.shift
    $out = File.open(ARGV[0],"w")
  else
    print("\n",
	  "xtemplate [-d <data-file>|-D <data-expr>|-x <xml-file>|-y <yaml-file>]\n",
	  "          [-t <template-file> | -T <serialized-template>]\n",
	  "          [-o <output-file>]\n",
          "          [--with-eruby|--with-erb]\n",
	  "xtemplate -c <template-file> [-o <output-file>]\n",
	  "          (serialize the template-file.)\n",
	  "\n",
	  "--show-time    print processing time\n",
	  "--use-amrita   use Amrita instead of XTemplate\n",
	  "--use-amrita-xml   use Amrita instead of XTemplate\n",
	  "\n")
    exit(0)
  end
  ARGV.shift
end

def amrita_data(data)
  case data
  when Hash
    newdata = {}
    attrs = {}
    nodes = {}
    data.each{|key,val|
      case key[0,1]
      when "@"
	attrs[key[1..-1].intern] = val
      when "."
	nodes = val
      else
	nodes[key.intern] = amrita_data(val)
      end
    }
    if( attrs.size > 0 )
      newdata = Amrita::a(attrs){ nodes }
    else
      data.each{|key, val|
	newdata[key.intern] = amrita_data(val)
      }
    end
    newdata
  when Array
    data.collect{|d| amrita_data(d)}
  else
    data
  end
end

def time(msg)
  t1 = Time.now
  r = yield
  t2 = Time.now
  if( $show_time )
    $stderr.print("#{msg}: #{t2 - t1}\n")
  end
  r
end

if( $filename )
  info['template']['filename'] = $filename
  info['template']['mtime']    = File.mtime($filename).to_s
else
  info['template']['filename'] = "-"
  info['template']['mtime'] = Time.now.to_s
end

if( $data.is_a?(XTemplate::XData) )
  $data = $data.to_hash
end
$data['xtemplate'] = info

if( $use_amrita )
  require 'amrita/template'
  $data = amrita_data($data)
  if( $filename )
    t = time("Preparation"){ Amrita::TemplateFile.new($filename) }
  else
    t = time("Preparation"){ Amrita::TemplateText.new($text) }
  end
  if( $use_compiler )
    t.use_compiler = true
  end
  if( $hint )
    t.set_hint_by_sample_data(amrita_data($hint))
  end
  if( ! $html )
    require 'amrita/xml'
    t.xml = true
  end
  time("Expansion"){ t.expand($out, $data) }
else
  if( $template )
    t = time("Preparation"){ XTemplate::XMLTemplate.load($template) }
  else
    if( $html )
      require 'xtemplate/html'
      if( $text )
	t = time("Preparation"){ XTemplate::HTMLTemplate.new($text) }
      elsif( $filename )
	t = time("Preparation"){ XTemplate::HTMLTemplate.new(File.open($filename)) }
      else
	t = time("Preparation"){ XTemplate::HTMLTemplate.new($stdin) }
      end
    else
      if( $text )
	t = time("Preparation"){ XTemplate::XMLTemplate.new($text) }
      elsif( $filename )
	t = time("Preparation"){ XTemplate::XMLTemplate.new(File.open($filename)) }
      else
	t = time("Preparation"){ XTemplate::XMLTemplate.new($stdin) }
      end
    end
  end
  if( $dump )
    $out.print(t.dump())
  else
    time("Expansion"){ t.expand2($out, $data, :plugin => $plugin ) }
  end
end
$out << "\n"
