#!/usr/bin/env ruby

$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")))
require 'nokogiri'
require 'optparse'
require 'ostruct'
require 'recog'
require 'recog/formatter'
require 'recog/verifier'
require 'recog/verify_reporter'

options = OpenStruct.new(color: false, detail: false, quiet: false, warnings: true, schema: nil)

option_parser = OptionParser.new do |opts|
  opts.banner = "Usage: #{$0} [options] XML_FINGERPRINT_FILE1 ..."
  opts.separator "Verifies that each fingerprint passes its internal tests."
  opts.separator ""
  opts.separator "Options"

  opts.on("-f", "--format FORMATTER",
          "Choose a formatter.",
          "  [s]ummary (default - failure/warning msgs and summary)",
          "  [q]uiet (configured failure/warning msgs only)",
          "  [d]etail  (fingerprint name with tests and expanded summary)") do |format|
    if format.start_with? 'd'
      options.detail = true
    end
    if format.start_with? 'q'
      options.quiet = true
    end
  end

  opts.on("-c", "--color", "Enable color in the output.") do
    options.color = true
  end

  opts.on("--[no-]warnings", "Track warnings") do |o|
    options.warnings = o
  end

  opts.on("--schema-location SCHEMA_FILE", "Location of the Recog XSD file. If not specified, validation will not be run.") do |schema_file|
    options.schema = Nokogiri::XML::Schema(File.read(schema_file))
  end

  opts.on("-h", "--help", "Show this message.") do
    puts opts
    exit
  end
end
option_parser.parse!(ARGV)

if ARGV.empty?
  $stderr.puts 'Missing XML fingerprint files'
  puts option_parser
  exit(1)
end

warnings = 0
failures = 0
formatter = Recog::Formatter.new(options, $stdout)
ARGV.each do |arg|
  Dir.glob(arg).each do |file|
    # Create a new reporter per XML file to hold context on success/warn/fails
    reporter  = Recog::VerifyReporter.new(options, formatter, file)

    begin
      # Validate the XML database against the recog schema first, if requested
      if options.schema
        errors = options.schema.validate(Nokogiri::XML(File.read(file)))
        if errors.size > 0
          reporter.report(0) do
            errors.each do |error|
              reporter.failure(error.message, error.line)
            end
          end
          # Skip validation of individual fingerprints since the XML itself
          # is likely malformed.
          next
        end
      end

      # Now read the XML file directly and validate the fingerprints
      # themselves
      db = Recog::DB.new(file)
      verifier = Recog::Verifier.new(db, reporter)
      verifier.verify
    rescue Recog::FingerprintParseError => e
      reporter.failure(e.message, e.line_number)
    rescue => e
      reporter.failure(e.message)
    ensure
      failures += reporter.failure_count
      warnings += reporter.warning_count
    end
  end
end

exit failures + warnings
