#!/usr/pkg/bin/ruby33
# frozen_string_literal: true

#
# Copyright (c) 2010-2019 Minero Aoki, Kenshi Muto
#               1999-2007 Minero Aoki
#
# This program is free software.
# You can distribute or modify this program under the terms of
# the GNU LGPL, Lesser General Public License version 2.1.
# For details of the GNU LGPL, see the file "COPYING".
#

$LOAD_PATH.unshift(File.realpath('../lib', __dir__))

require 'review/preprocessor'
require 'review/version'
require 'review/extentions'
require 'review/logger'
require 'review/lineinput'
require 'review/loggable'
require 'stringio'
require 'fileutils'
require 'optparse'
require 'tempfile'

include ReVIEW::Loggable

def sigmain
  Signal.trap(:INT) { exit 1 }
  unless RUBY_PLATFORM.match?(/mswin(?!ce)|mingw|cygwin|bccwin/)
    Signal.trap(:PIPE, 'IGNORE')
  end
  main
rescue Errno::EPIPE
  exit 0
end

def parse_options
  param = {}

  mode = :output
  opts = OptionParser.new
  opts.version = ReVIEW::VERSION
  opts.banner = "Usage: #{File.basename($PROGRAM_NAME)} [-c|-d|-s|--replace] [<file>...]"
  opts.on('-c', '--check', 'Check if preprocess is needed.') { mode = :check }
  opts.on('-d', '--diff', 'Show diff from current file.') { mode = :diff }
  opts.on('--replace', 'Replace file by preprocessed one.') { mode = :replace }
  opts.on('--tabwidth=WIDTH', "Replace tabs with space characters. (0: don't replace)") { |width| param['tabwidth'] = width.to_i }
  opts.on('--help', 'Print this message and quit.') do
    puts opts.help
    exit 0
  end
  begin
    opts.parse!
  rescue OptionParser::ParseError => e
    error e.message
    $stderr.puts opts.help
    exit 1
  end

  [param, mode]
end

def main
  @logger = ReVIEW.logger
  if File.file?('review-preproc-ext.rb')
    if ENV['REVIEW_SAFE_MODE'].to_i & 2 > 0
      warn 'review-preproc-ext.rb is prohibited in safe mode. ignored.'
    else
      Kernel.load(File.expand_path('review-preproc-ext.rb'))
    end
  end

  param, mode = parse_options
  pp = ReVIEW::Preprocessor.new(param)
  ARGV.each do |path|
    case mode
    when :output
      $stdout.write(pp.process(path))
    when :replace
      output = pp.process(path)
      File.write(path, output)
    when :diff, :check
      Tempfile.create('review.pptmp') do |tmp_io|
        tmp = tmp_io.path
        tmp_io.write(pp.process(path))
        if mode == :check
          system("diff -qu #{path} #{tmp} >/dev/null || echo #{path}")
        else
          system("diff -u #{path} #{tmp}")
        end
      end
    else
      raise "must not happen: #{mode}"
    end
  end
rescue ReVIEW::Error => e
  raise if $DEBUG

  error! e.message
end

sigmain
