#!/usr/bin/env ruby

$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))

require 'getoptlong'
require 'rdf-config'

def help
  if __FILE__ == $PROGRAM_NAME
    puts DATA.read
  else
    usage = File.read(File.expand_path(__FILE__)).split("__END__\n").last
    puts usage
  end
  exit
end

opts = {
  config_dir: nil,
  mode: nil
}

args = GetoptLong.new(
  ['--config',   '-c',  GetoptLong::REQUIRED_ARGUMENT],
  ['--help',     '-h',  GetoptLong::NO_ARGUMENT],
  ['--senbero',         GetoptLong::NO_ARGUMENT],
  ['--schema',          GetoptLong::OPTIONAL_ARGUMENT],
  ['--endpoint',        GetoptLong::OPTIONAL_ARGUMENT],
  ['--sparql',          GetoptLong::OPTIONAL_ARGUMENT],
  ['--url',             GetoptLong::NO_ARGUMENT],
  ['--query',           GetoptLong::OPTIONAL_ARGUMENT],
  ['--join',            GetoptLong::OPTIONAL_ARGUMENT],
  ['--sparqlist',       GetoptLong::OPTIONAL_ARGUMENT],
  ['--grasp',           GetoptLong::OPTIONAL_ARGUMENT],
  ['--grasp-ns',        GetoptLong::OPTIONAL_ARGUMENT],
  ['--stanza',          GetoptLong::OPTIONAL_ARGUMENT],
  ['--stanza_rb',       GetoptLong::OPTIONAL_ARGUMENT],
  ['--shex',            GetoptLong::OPTIONAL_ARGUMENT],
  ['--convert',         GetoptLong::OPTIONAL_ARGUMENT],
  ['--context',         GetoptLong::OPTIONAL_ARGUMENT],
  ['--output',          GetoptLong::OPTIONAL_ARGUMENT],
  ['--output-interval', GetoptLong::OPTIONAL_ARGUMENT],
  ['--debug',           GetoptLong::OPTIONAL_ARGUMENT]
)
args.ordering = GetoptLong::RETURN_IN_ORDER

debug_mode = false
target_opt_name = ''
opt_values = {}
begin
  args.each_option do |name, value|
    name = name.to_s.strip
    target_opt_name = name unless name.empty?
    if opt_values.key?(target_opt_name)
      opt_values[target_opt_name] << value
    else
      opt_values[target_opt_name] = [value]
    end
  end
rescue StandardError
  puts
  help
  exit(1)
end

ONLY_ONE_VALUE_OPTS = %w[--convert --context --output --output-interval].freeze
arg_values = []
opt_values.each do |opt_name, values|
  next if values.empty?

  value = if values.size > 1
            if ONLY_ONE_VALUE_OPTS.include?(opt_name)
              arg_values << values[1..]
              values.first
            else
              values
            end
          else
            values.first
          end
  case opt_name
  when /--config/
    opts[:config_dir] = value
  when /--senbero/
    opts[:mode] = :senbero
  when /--schema/
    opts[:mode] = :chart
    opts[:schema_opt] = value
  when /--sparqlist/
    opts[:mode] = :sparqlist
  when /--sparql/
    opts[:mode] = :sparql
    opts[:sparql] = value
  when /--url/
    opts[:mode] = :sparql_url
  when /--query/
    opts[:query] = value
  when /--endpoint/
    opts[:endpoint_name] = value
  when /--join/
    opts[:mode] = :sparql
    opts[:join] = value
  when '--grasp'
    opts[:mode] = :grasp
    opts[:output_dir] = value
    opts[:add_namespace] = false
  when '--grasp-ns'
    opts[:mode] = :grasp
    opts[:output_dir] = value
    opts[:add_namespace] = true
  when /--stanza_rb/
    opts[:mode] = :stanza_rb
    opts[:stanza_name] = value
  when /--stanza/
    opts[:mode] = :stanza_js
    opts[:stanza_name] = value
  when /--shex/
    opts[:mode] = :shex
  when '--convert'
    opts[:mode] = :convert
    opts[:format] = value
  when '--output-interval'
    opts[:output_interval] = value
  when '--output'
    opts[:output_path] = value
  when '--debug'
    debug_mode = true
  else
    arg_values << value
  end
end
arg_values.flatten!

opts[:mode] = :sparql if opts[:mode].nil? && (opts.key?(:query) || opts.key?(:endpoint_name))

if opts[:mode] == :convert
  if arg_values.empty?
    if opts[:config_dir].is_a?(Array) && opts[:config_dir].size > 1
      opts[:convert_source] = opts[:config_dir].last
      opts[:config_dir] = opts[:config_dir].first
    end
  else
    opts[:convert_source] = arg_values.last
  end
end

if opts[:config_dir] && opts[:mode]
  begin
    rdf_config = RDFConfig.new(opts)
    rdf_config.exec(opts)
  rescue StandardError => e
    warn e.message
    warn e.backtrace if debug_mode
    exit(1)
  end
else
  help
end

__END__
NAME
    rdf-config -- RDF model to SPARQL, Schema, Stanza converter

SYNOPSIS
    rdf-config --config path/to/config/name --sparql     [queryname]
    rdf-config --config path/to/config/name --query      var1 var2=value var3 ...

    Use with --sparql or --query options:
    rdf-config --config path/to/config/name --endpoint   [endpointname]
    rdf-config --config path/to/config/name --url

    rdf-config --config path/to/config/name --schema
    rdf-config --config path/to/config/name --senbero
    rdf-config --config path/to/config/name --grasp      [output_directory]
    rdf-config --config path/to/config/name --grasp-ns   [output_directory]
    rdf-config --config path/to/config/name --stanza     [stanzaname]
    rdf-config --config path/to/config/name --shex
    rdf-config --config path/to/config/name --convert [output_type] [input_file_or_directory]
      Valid output_type values are :turtle, :jsondld, :jsonl, :context
    rdf-config --help

DESCRIPTION

    Read a RDF data model from config/name/ directory
    then generate SPARQL query, exec SPARQL query,
    generate Schema chart, and generate Stanza.

    Configuration files of a RDF model are written
    in the YAML format.

    * config/name/model.yaml: RDF deta model structure and variable names
    * config/name/endpoint.yaml: SPARQL endpoint (default endpoint:)
    * config/name/prefix.yaml: URI prefixes
    * config/name/sparql.yaml: SPARQL definition
    * config/name/stanza.yaml: TogoStanza definition
    * config/name/metadata.yaml: Metadata compatible with NBRC RDF portal
    * config/name/metadata_ja.yaml: Japanese version of Metadata

