#!/usr/bin/ruby.ruby3.4
# frozen_string_literal: true

require "pathname"
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", Pathname.new(__FILE__).realpath)

STDERR.puts <<~MESSAGE if defined?(Bundler)
    WARNING: Using `bundle exec` to start the server is unnecessary, and will make startup slower. Use `bin/rails s` or `bin/unicorn`.
  MESSAGE

require "rubygems"
require "bundler/setup"
require "fileutils"

dev_mode = false

# in development do some fussing around, to automate config
if !ARGV.include?("-E") && !ARGV.include?("--env") &&
     (%w[development test].include?(ENV["RAILS_ENV"]) || !ENV["RAILS_ENV"])
  dev_mode = true

  ARGV.push("-N")
  if !ARGV.include?("-c") && !ARGV.include?("--config-file")
    ARGV.push("-c")
    ARGV.push(File.expand_path("../../config/unicorn.conf.rb", Pathname.new(__FILE__).realpath))
  end

  # we do not want to listen on 2 ports, so lets fix it
  if (idx = ARGV.index("-p")) && (port = ARGV[idx + 1].to_i) > 0
    ENV["UNICORN_PORT"] ||= port.to_s
  end

  ENV["UNICORN_PORT"] ||= "9292"

  if ARGV.delete("-x")
    puts "Running without sidekiq"
    ENV["UNICORN_SIDEKIQS"] = "0"
  end

  ENV["UNICORN_SIDEKIQS"] ||= "1"
end

if ARGV.include?("--help")
  fork { load Gem.bin_path("unicorn", "unicorn") }
  Process.wait
  puts "Extra Discourse Options:"
  puts "  -x                       run without sidekiq"
  exit
end

# this dev_mode hackery enables the following to be used to restart unicorn:
#
# pkill -USR2 -f 'ruby bin/unicorn'
#
# This is handy if you want to bind a key to restarting unicorn in dev

if dev_mode
  UNICORN_DEV_SUPERVISOR_PID = Process.pid

  restart = true
  while restart
    restart = false
    pid =
      fork do
        begin
          load Gem.bin_path("unicorn", "unicorn")
        rescue ArgumentError => err
          if (err.message =~ /Already running on PID/)
            puts "\n"
            puts "Unicorn is already running!\n"
            pid = err.message[/PID:(\d+)/, 1]&.to_i
            puts "\n"
            puts "kill -9 #{pid} to stop the existing unicorn master process, then try again."
          else
            raise err
          end
        end
      end
    done = false

    Signal.trap("INT") do
      # wait for parent to be done
    end

    Signal.trap("USR2") do
      Process.kill("QUIT", pid)
      puts "RESTARTING UNICORN"
      restart = true
    end

    Signal.trap("TERM") { Process.kill("TERM", pid) }

    while !done
      sleep 1
      done = Process.waitpid(pid, Process::WNOHANG)
    end
  end
else
  load Gem.bin_path("unicorn", "unicorn")
end
