# typed: true
class Scraper::ClientFactory
  @http_clients = Concurrent::ThreadLocalVar.new() { {} }
  @gallery_dl_clients = Concurrent::ThreadLocalVar.new(nil)

  # for testing only
  def self.http_client_mock=(mock)
    raise unless Rails.env.test?
    @http_client_mock = mock
  end

  def self.gallery_dl_client_mock=(mock)
    raise unless Rails.env.test?
    @gallery_dl_client_mock = mock
  end

  # public API
  def self.get_gallery_dl_client
    # TODO - can probably allow development to hit real websites
    if Rails.env.test? || Rails.env.development?
      @gallery_dl_client_mock || raise("no gallery dl mock set")
    else
      _gallery_dl_client_impl
    end
  end

  def self.get_twitter_http_client
    if Rails.env.test? || Rails.env.development?
      @http_client_mock || raise("no http client mock set")
    else
      _http_client_impl(:twitter, Scraper::TwitterHttpClientConfig)
    end
  end

  def self.get_generic_http_client
    if Rails.env.test? || Rails.env.development?
      @http_client_mock || raise("no http client mock set")
    else
      _http_client_impl(:generic, Scraper::GenericHttpClientConfig)
    end
  end

  def self.get_fa_http_client
    if Rails.env.test?
      @http_client_mock || raise("no http client mock set")
    else
      _http_client_impl(:fa, Scraper::FaHttpClientConfig)
    end
  end

  def self.get_sofurry_http_client
    if Rails.env.test?
      @http_client_mock || raise("no http client mock set")
    else
      _http_client_impl(:sofurry, Scraper::SofurryHttpClientConfig)
    end
  end

  def self.get_e621_http_client
    if Rails.env.test?
      @http_client_mock || raise("no http client mock set")
    else
      _http_client_impl(:e621, Scraper::E621HttpClientConfig)
    end
  end

  def self.get_inkbunny_http_client
    if Rails.env.test?
      @http_client_mock || raise("no http client mock set")
    else
      _http_client_impl(:inkbunny, Scraper::InkbunnyHttpClientConfig)
    end
  end

  def self.get_fur_archiver_http_client
    if Rails.env.test?
      @http_client_mock || raise("no http client mock set")
    else
      _http_client_impl(:fur_archiver, Scraper::FurArchiverHttpClientConfig)
    end
  end

  def self._gallery_dl_client_impl
    @gallery_dl_clients.value ||=
      begin
        proxy_config =
          Rails.application.config.x.proxy || raise("no proxy config")
        if proxy_config[:gallery_dl].blank?
          raise(
            "no gallery_dl host defined for proxy config #{proxy_config[:name]}",
          )
        end
        Scraper::GalleryDlClient.new(
          proxy_config[:name],
          proxy_config[:gallery_dl],
        )
      end
  end

  def self._http_client_impl(key, config_klass)
    @http_clients.value[key] ||= begin
      Scraper::HttpClient.new(config_klass.new, Scraper::CurlHttpPerformer.new)
    end
  end
end
