#!/usr/bin/env ruby
# frozen_string_literal: true

require "optparse"

original_args = ARGV.dup
options = {}
parser = OptionParser.new do |opts|
  opts.banner = "Usage: ruby-lsp [options]"

  opts.on("--version", "Print ruby-lsp version") do
    require "ruby-lsp"
    puts RubyLsp::VERSION
    exit(0)
  end

  opts.on("--debug", "Launch the Ruby LSP with a debugger attached") do
    options[:debug] = true
  end

  opts.on("--time-index", "Measure the time it takes to index the project") do
    options[:time_index] = true
  end

  opts.on(
    "--branch [BRANCH]",
    "Launch the Ruby LSP using the specified branch rather than the release version",
  ) do |branch|
    options[:branch] = branch
  end

  opts.on(
    "--experimental",
    "Run pre-release versions of the Ruby LSP",
  ) do
    options[:experimental] = true
  end

  opts.on("-h", "--help", "Print this help") do
    puts opts.help
    puts
    puts "See https://shopify.github.io/ruby-lsp/ for more information"
    exit(0)
  end
end

begin
  parser.parse!
rescue OptionParser::InvalidOption => e
  warn(e)
  warn("")
  warn(parser.help)
  exit(1)
end

# When we're running without bundler, then we need to make sure the custom bundle is fully configured and re-execute
# using `BUNDLE_GEMFILE=.ruby-lsp/Gemfile bundle exec ruby-lsp` so that we have access to the gems that are a part of
# the application's bundle
if ENV["BUNDLE_GEMFILE"].nil?
  require_relative "../lib/ruby_lsp/setup_bundler"

  begin
    bundle_gemfile, bundle_path, bundle_app_config = RubyLsp::SetupBundler.new(Dir.pwd, **options).setup!
  rescue RubyLsp::SetupBundler::BundleNotLocked
    warn("Project contains a Gemfile, but no Gemfile.lock. Run `bundle install` to lock gems and restart the server")
    exit(78)
  end

  env = { "BUNDLE_GEMFILE" => bundle_gemfile }
  env["BUNDLE_PATH"] = bundle_path if bundle_path
  env["BUNDLE_APP_CONFIG"] = bundle_app_config if bundle_app_config
  exit exec(env, "bundle exec ruby-lsp #{original_args.join(" ")}")
end

require "ruby_lsp/load_sorbet"

$LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
require "ruby_lsp/internal"

if options[:debug]
  if ["x64-mingw-ucrt", "x64-mingw32"].include?(RUBY_PLATFORM)
    $stderr.puts "Debugging is not supported on Windows"
    exit 1
  end

  begin
    ENV.delete("RUBY_DEBUG_IRB_CONSOLE")
    require "debug/open_nonstop"
  rescue LoadError
    $stderr.puts("You need to install the debug gem to use the --debug flag")
  end
end

if options[:time_index]
  require "benchmark"

  index = RubyIndexer::Index.new

  result = Benchmark.realtime { index.index_all }
  entries = index.instance_variable_get(:@entries)
  entries_by_entry_type = entries.values.flatten.group_by(&:class)

  puts <<~MSG
    Ruby LSP v#{RubyLsp::VERSION}: Indexing took #{result.round(5)} seconds and generated:
    - #{entries_by_entry_type.map { |k, v| "#{k.name.split("::").last}: #{v.size}" }.join("\n- ")}
  MSG
  return
end

RubyLsp::Server.new.start