class RubyLsp::Tapioca::Addon

def activate(global_state, outgoing_queue)

def activate(global_state, outgoing_queue)
  @global_state = global_state
  return unless @global_state.enabled_feature?(:tapiocaAddon)
  @index = @global_state.index
  @outgoing_queue = outgoing_queue
  Thread.new do
    # Get a handle to the Rails add-on's runtime client. The call to `rails_runner_client` will block this thread
    # until the server has finished booting, but it will not block the main LSP. This has to happen inside of a
    # thread
    addon = T.cast(::RubyLsp::Addon.get("Ruby LSP Rails", ">= 0.3.17", "< 0.4"), ::RubyLsp::Rails::Addon)
    @rails_runner_client = addon.rails_runner_client
    @outgoing_queue << Notification.window_log_message("Activating Tapioca add-on v#{version}")
    @rails_runner_client.register_server_addon(File.expand_path("server_addon.rb", __dir__))
  rescue IncompatibleApiError
    # The requested version for the Rails add-on no longer matches. We need to upgrade and fix the breaking
    # changes
    @outgoing_queue << Notification.window_log_message(
      "IncompatibleApiError: Cannot activate Tapioca LSP add-on",
      type: Constant::MessageType::WARNING,
    )
  end
end

def deactivate

def deactivate
end

def file_updated?(change, path)

def file_updated?(change, path)
  case change[:type]
  when Constant::FileChangeType::CREATED
    @file_checksums[path] = Zlib.crc32(File.read(path)).to_s
    return true
  when Constant::FileChangeType::CHANGED
    current_checksum = Zlib.crc32(File.read(path)).to_s
    if @file_checksums[path] == current_checksum
      T.must(@outgoing_queue) << Notification.window_log_message(
        "File has not changed. Skipping #{path}",
        type: Constant::MessageType::INFO,
      )
    else
      @file_checksums[path] = current_checksum
      return true
    end
  when Constant::FileChangeType::DELETED
    @file_checksums.delete(path)
  else
    T.must(@outgoing_queue) << Notification.window_log_message(
      "Unexpected file change type: #{change[:type]}",
      type: Constant::MessageType::WARNING,
    )
  end
  false
end

def initialize

def initialize
  super
  @global_state = T.let(nil, T.nilable(RubyLsp::GlobalState))
  @rails_runner_client = T.let(nil, T.nilable(RubyLsp::Rails::RunnerClient))
  @index = T.let(nil, T.nilable(RubyIndexer::Index))
  @file_checksums = T.let({}, T::Hash[String, String])
  @outgoing_queue = T.let(nil, T.nilable(Thread::Queue))
end

def name

def name
  "Tapioca"
end

def version

def version
  "0.1.0"
end

def workspace_did_change_watched_files(changes)

def workspace_did_change_watched_files(changes)
  return unless T.must(@global_state).enabled_feature?(:tapiocaAddon)
  return unless @rails_runner_client # Client is not ready
  constants = changes.flat_map do |change|
    path = URI(change[:uri]).to_standardized_path
    next if path.end_with?("_test.rb", "_spec.rb")
    next unless file_updated?(change, path)
    entries = T.must(@index).entries_for(change[:uri])
    next unless entries
    entries.filter_map do |entry|
      entry.name if entry.class == RubyIndexer::Entry::Class || entry.class == RubyIndexer::Entry::Module
    end
  end.compact
  return if constants.empty?
  @rails_runner_client.trigger_reload
  @rails_runner_client.delegate_notification(
    server_addon_name: "Tapioca",
    request_name: "dsl",
    constants: constants,
  )
end