#! /usr/bin/ruby

#==============================================================================#
# $Id: exerb,v 1.17 2003/12/03 08:28:45 yuya Exp $
#==============================================================================#

require 'getoptlong'
require 'exerb/recipe'
require 'exerb/executable'
require 'exerb/resource'

#==============================================================================#

module ExerbCommand

  OPTIONS = [
    ['--corename', '-c', GetoptLong::REQUIRED_ARGUMENT, 'specifies exerb-core name.'],
    ['--corefile', '-C', GetoptLong::REQUIRED_ARGUMENT, 'specifies exerb-core file.'],
    ['--outfile',  '-o', GetoptLong::REQUIRED_ARGUMENT, 'specifies output file.'],
    ['--kcode',    '-k', GetoptLong::REQUIRED_ARGUMENT, 'specifies kanji code. (none/euc/sjis/utf8)'],
    ['--verbose',  '-v', GetoptLong::NO_ARGUMENT,       'enable verbose mode.'],
    ['--debug',    '-g', GetoptLong::NO_ARGUMENT,       'enable debug mode.'],
    ['--execute',  '-e', GetoptLong::NO_ARGUMENT,       'execute the created executable file.'],
    ['--version',  '-V', GetoptLong::NO_ARGUMENT,       'display version number.'],
    ['--help',     '-h', GetoptLong::NO_ARGUMENT,       'display this information.'],
  ]

  def self.main(argv)
    options = self.parse_options(argv)

    self.print_version_and_exit if options[:version]
    self.print_usage_and_exit   if options[:help] || argv.size < 1

    recipe_file  = argv.shift
    archive_file = self.make_filename(recipe_file, 'exa')

    recipe    = Exerb::Recipe.new_from_file(recipe_file)
    core_file = self.select_core_file(options, recipe)
    out_file  = self.select_out_file(options, recipe, recipe_file)

    if options[:verbose]
      puts("Recipe File  : #{recipe_file}")
      puts("Archive File : #{archive_file}") if options[:debug]
      puts("Core File    : #{core_file}")
      puts("Output File  : #{out_file}")
    end

    recipe.archive.kcode = options[:kcode] if options[:kcode]
    recipe.archive.write_to_file(archive_file) if options[:debug]

    executable = Exerb::Executable.new_from_file(core_file)
    executable.rsrc.add_archive(recipe.archive)
    executable.write_to_file(out_file)

    exec(File.expand_path(out_file)) if options[:execute]

    exit(0)
  rescue Exerb::ExerbError => e
    STDERR.puts("exerb: #{e.message}")
    exit(1)
  end

  def self.parse_options(argv)
    options = {}
    config  = OPTIONS.collect { |ary| ary[0, 3] }

    parser = GetoptLong.new
    parser.set_options(*config)
    parser.each_option { |name, argument|
      options[name.sub(/^--/, '').intern] = argument
    }

    options[:verbose]  = !!options[:verbose]
    options[:debug]    = !!options[:debug]
    options[:execute]  = !!options[:execute]
    options[:version]  = !!options[:version]
    options[:help]     = !!options[:help]

    return options
  rescue GetoptLong::InvalidOption
    exit(1)
  end

  def self.print_version_and_exit
    puts "Exerb #{Exerb::VERSION}"
    exit(1)
  end

  def self.print_usage_and_exit
    puts("Exerb #{Exerb::VERSION}")
    puts

    puts("Usage: exerb [options] recipe-file")
    puts

    puts("Options:")
    OPTIONS.each { |long, short, arg, comment|
      printf("  %s  %-10s  %s\n", short, long, comment)
    }

    exit(1)
  end

  def self.make_filename(filename, extension)
    return filename.sub(/(\.exr$|$)/i, '.' + extension)
  end

  def self.select_core_file(options, recipe)
    core_file   = options[:corefile]
    core_file ||= Exerb::Utility.find_core_by_name(options[:corename], true) if options[:corename]
    core_file ||= recipe.corefile
    core_file ||= Exerb::Utility.find_core_by_name('cui')
    core_file ||= Exerb::Utility.find_core_by_name('gui')
    core_file ||= raise(Exerb::ExerbError, "a core file isn't specified in the recipe file and command line options.")

    return core_file
  end

  def self.select_out_file(options, recipe, recipe_file)
    out_file   = options[:outfile]
    out_file ||= recipe.outfile
    out_file ||= self.make_filename(recipe_file, 'exe')

    return out_file
  end

end

#==============================================================================#

ExerbCommand.main(ARGV)

#==============================================================================#
#==============================================================================#
