class Rufo::Command

def self.parse_options(argv)

def self.parse_options(argv)
  exit_code, want_check = true, false
  filename_for_dot_rufo = nil
  loglevel = :log
  OptionParser.new do |opts|
    opts.version = Rufo::VERSION
    opts.banner = "Usage: rufo files or dirs [options]"
    opts.on("-c", "--check", "Only check formating changes") do
      want_check = true
    end
    opts.on("--filename=value", "Filename to use to lookup .rufo (useful for STDIN formatting)") do |value|
      filename_for_dot_rufo = value
    end
    opts.on("-x", "--simple-exit", "Return 1 in the case of failure, else 0") do
      exit_code = false
    end
    opts.on(Rufo::Logger::LEVELS, "--loglevel[=LEVEL]", "Change the level of logging for the CLI. Options are: error, warn, log (default), debug, silent") do |value|
      loglevel = value.to_sym
    end
    opts.on("-h", "--help", "Show this help") do
      puts opts
      exit
    end
  end.parse!(argv)
  [want_check, exit_code, filename_for_dot_rufo, loglevel]
end

def self.run(argv)

def self.run(argv)
  want_check, exit_code, filename_for_dot_rufo, loglevel = parse_options(argv)
  new(want_check, exit_code, filename_for_dot_rufo, loglevel).run(argv)
end

def exit_code(status_code)

def exit_code(status_code)
  if @exit_code
    status_code
  else
    case status_code
    when CODE_OK, CODE_CHANGE
      0
    else
      1
    end
  end
end

def format(code, dir, erb: false)

def format(code, dir, erb: false)
  options = @dot_file.get_config_in(dir) || {}
  if erb
    formatter = Rufo::ErbFormatter.new(code, **options)
  else
    formatter = Rufo::Formatter.new(code, **options)
  end
  formatter.format
  result = formatter.result
  result
end

def format_args(args)

def format_args(args)
  top_level_dot_file = @filename_for_dot_rufo || Dir.getwd
  options = @dot_file.get_config_in(top_level_dot_file) || {}
  file_finder = Rufo::FileFinder.new(
    args, includes: options[:includes], excludes: options[:excludes],
  )
  files = file_finder.to_a
  changed = false
  syntax_error = false
  files_exist = false
  files.each do |(exists, file)|
    if exists
      files_exist = true
    else
      logger.warn("Error: file or directory not found: #{file}")
      next
    end
    result = format_file(file)
    changed |= result == CODE_CHANGE
    syntax_error |= result == CODE_ERROR
  end
  return CODE_ERROR unless files_exist
  case
  when syntax_error then CODE_ERROR
  when changed      then CODE_CHANGE
  else                   CODE_OK
  end
end

def format_file(filename)

def format_file(filename)
  logger.debug("Formatting: #{filename}")
  code = File.read(filename)
  begin
    location = @filename_for_dot_rufo || File.dirname(filename)
    erb = filename.end_with?(".erb")
    result = format(code, location, erb: erb)
  rescue Rufo::SyntaxError => e
    # We ignore syntax errors as these might be template files
    # with .rb extension
    logger.warn("#{filename}:#{e.lineno} #{e.message}")
    return CODE_ERROR
  end
  if code.force_encoding(result.encoding) != result
    if @want_check
      logger.warn("Formatting #{filename} produced changes")
    else
      File.write(filename, result)
      logger.log("Format: #{filename}")
    end
    return CODE_CHANGE
  end
rescue Rufo::SyntaxError => e
  logger.error("#{filename}:#{e.lineno} #{e.message}")
  CODE_ERROR
rescue => e
  logger.error("You've found a bug!")
  logger.error("It happened while trying to format the file #{filename}")
  logger.error("Please report it to https://github.com/ruby-formatter/rufo/issues with code that triggers it\n")
  raise e
end

def format_stdin

def format_stdin
  code = STDIN.read
  erb = @filename_for_dot_rufo && @filename_for_dot_rufo.end_with?(".erb")
  result = format(code, @filename_for_dot_rufo || Dir.getwd, erb: erb)
  print(result) if !@want_check
  code == result ? CODE_OK : CODE_CHANGE
rescue Rufo::SyntaxError => e
  logger.error("STDIN is invalid code. Error on line:#{e.lineno} #{e.message}")
  CODE_ERROR
rescue => e
  logger.error("You've found a bug!")
  logger.error("Please report it to https://github.com/ruby-formatter/rufo/issues with code that triggers it\n")
  raise e
end

def initialize(want_check, exit_code, filename_for_dot_rufo, loglevel)

def initialize(want_check, exit_code, filename_for_dot_rufo, loglevel)
  @want_check = want_check
  @exit_code = exit_code
  @filename_for_dot_rufo = filename_for_dot_rufo
  @dot_file = Rufo::DotFile.new
  @logger = Rufo::Logger.new(loglevel)
end

def run(argv)

def run(argv)
  status_code = if argv.empty?
      format_stdin
    else
      format_args argv
    end
  exit exit_code(status_code)
end