#!/usr/bin/env ruby
require 'rubygems'
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", 'lib')))
require 'rdf/rdfa'
require 'sparql/grammar'
require File.expand_path(File.join(File.dirname(__FILE__), "..", 'spec', 'spec_helper'))
require File.expand_path(File.join(File.dirname(__FILE__), "..", 'spec', 'test_helper'))
require 'getoptlong'

def run_tc(tc, options)
  input_uri = tc.input(options[:host_language], options[:version])
  results_uri = tc.results(options[:host_language], options[:version])

  STDOUT.write "run #{tc.name}"

  if options[:verbose]
    puts("\nTestCase: #{tc.inspect}") 
    puts("\nInput:\n" + Kernel.open(input_uri) {|f| f.read}) 
    puts("\nQuery:\n" + Kernel.open(results_uri) {|f| f.read})
  end

  pg = RDF::Graph.new if options[:processor_graph]

  begin
    reader = RDF::RDFa::Reader.new(Kernel.open(input_uri),
      :base_uri => input_uri,
      :validate => options[:validate],
      :processor_graph => pg,
      :version => options[:version])

    graph = RDF::Graph.new << reader
  rescue Exception => e
    puts "#{"exception:" unless options[:quiet]}: #{e}"
    if options[:quiet]
      return
    else
      raise
    end
  end
  
  puts("\nResult:\n" + graph.dump(options[:format])) unless options[:quiet]
  
  begin
    result = SPARQL::Grammar.parse(Kernel.open(results_uri)).execute(graph)
  rescue Exception => e
    puts "#{"exception:" unless options[:quiet]}: #{e}"
    return
  end
  puts "#{"test result:" unless options[:quiet]} #{(result == (tc.expectedResults || true)) ? 'ok' : 'fail'}"
  
  if pg && !options[:quiet]
    puts "\nProcessor Graph:\n"
    puts pg.inspect
    RDF::Writer.for(options[:format]).new do |writer|
      writer << pg
    end
  end
end

options = {
  :verbose         => false,
  :quite           => false,
  :validate        => false,
  :format          => :ntriples,
  :processor_graph => nil,
  :host_language   => "xhtml1",
  :version         => "rdfa1.1"
}

opts = GetoptLong.new(
  ["--help", "-?", GetoptLong::NO_ARGUMENT],
  ["--dbg", GetoptLong::NO_ARGUMENT],
  ["--format", GetoptLong::REQUIRED_ARGUMENT],
  ["--host-language", "-h", GetoptLong::OPTIONAL_ARGUMENT],
  ["--processor-graph", GetoptLong::NO_ARGUMENT],
  ["--quiet", GetoptLong::NO_ARGUMENT],
  ["--validate", GetoptLong::NO_ARGUMENT],
  ["--verbose", GetoptLong::NO_ARGUMENT],
  ["--version", "-v", GetoptLong::OPTIONAL_ARGUMENT]
)

def help(options)
  puts "Usage: #{$0} [options] [test-number ...]"
  puts "Options:"
  puts "      --dump:               Dump raw output, otherwise serialize to Ruby"
  puts "      --debug:              Display detailed debug output"
  puts "      --format:             Format for output, defaults to #{options[:format].inspect}"
  puts "      --host-language:      Run for specified host language, defaults to #{options[:host_language]}"
  puts "      --processor-graph:    Output processor graph"
  puts "      --quiet:              Minimal output"
  puts "      --validate:           Validate input"
  puts "      --verbose:            Verbose processing"
  puts "      --version:            Version of processor to use (rdf1.0, rdf1.1). Defaults to #{options[:version]}"
  puts "      --help,-?:            This message"
  exit(0)
end

opts.each do |opt, arg|
  case opt
  when '--help'             then help(options)
  when '--verbose'          then options[:verbose] = true
  when '--quiet'            then options[:quiet] = true
  when '--dbg'              then ::RDF::RDFa::debug = true
  when '--format'           then options[:format] = arg.to_sym
  when '--processor-graph'  then options[:processor_graph] = true
  when '--host-language'    then options[:host_language] = arg
  when '--version'          then options[:version] = arg
  when '--validate'         then options[:validate] = true
  end
end

Fixtures::TestCase.for_specific(options[:host_language], options[:version]) do |tc|
  next unless ARGV.empty? || ARGV.any? {|n| tc.name.match(/#{n}/)}
  run_tc(tc, options)
end