#! /usr/bin/ruby

#==============================================================================#
# $Id: exerb,v 1.6 2003/11/17 17:56:13 yuya Exp $
#==============================================================================#

require 'getoptlong'
require 'exerb/exerb'

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

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)'],
    ['--compress', '-z', GetoptLong::NO_ARGUMENT,       'enable archive compression. (using Ruby/zlib)'],
    ['--verbose',  '-v', GetoptLong::NO_ARGUMENT,       'enable verbose mode.'],
    ['--debug',    '-g', GetoptLong::NO_ARGUMENT,       'enable debug mode.'],
    ['--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)

    if options[:version]
      self.print_version
      exit(1)
    end

    if options[:help] || argv.size < 1
      self.print_usage
      exit(1)
    end

    recipe_file  = argv[0]
    archive_file = self.make_filename(recipe_file, 'exa')

    recipe  = Exerb::Recipe.new_from_file(recipe_file)
    archive = recipe.archive

    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_filename("ruby#{RUBY_VERSION.delete('.')}c.rbx")
    core_file ||= Exerb::Utility.find_core_by_filename("ruby#{RUBY_VERSION.delete('.')}g.rbx")
    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.")

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

    kcode   = options[:kcode]
    kcode ||= recipe.kcode
    kcode ||= 'none'

    archive.compress   = options[:compress]
    archive.compress ||= recipe.compress

    puts("Recipe File  : #{recipe_file}")
    puts("Archive File : #{archive_file}") if options[:debug]
    puts("Core File    : #{core_file}")
    puts("Compress     : #{archive.compress ? 'yes' : 'no'}")
    puts("Output File  : #{out_file}")

    if options[:debug]
      File.open(archive_file, 'wb') { |file|
        file.write(archive.pack)
      }
    end

    core       = Exerb::Core.new_from_file(core_file)
    executable = Exerb::Executable.new(core, archive, kcode)
    executable.output_to_file(out_file)

    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[:compress] = !!options[:compress]
    options[:verbose]  = !!options[:verbose]
    options[:debug]    = !!options[:debug]
    options[:version]  = !!options[:version]
    options[:help]     = !!options[:help]

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

  def self.print_version
    puts "Exerb #{Exerb::VERSION}"
  end

  def self.print_usage
    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)
    }
    puts
  end

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

end

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

ExerbCommand.main(ARGV)

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