# frozen_string_literal: true

require 'i18n/backend/pluralization'

module I18n
  module Backend
    class DiscourseI18n < I18n::Backend::Simple
      include I18n::Backend::Fallbacks
      include I18n::Backend::Pluralization

      def available_locales
        LocaleSiteSetting.supported_locales.map(&:to_sym)
      end

      def reload!
        @pluralizers = {}
        super
      end

      # force explicit loading
      def load_translations(*filenames)
        unless filenames.empty?
          filenames.flatten.each { |filename| load_file(filename) }
        end
      end

      def pluralize(locale, entry, count)
        begin
          super
        rescue I18n::InvalidPluralizationData => e
          raise e if I18n.fallbacks[locale] == [locale]
          throw(:exception, e)
        end
      end

      def self.create_search_regexp(query, as_string: false)
        regexp = Regexp.escape(query)

        regexp.gsub!(/['‘’‚‹›]/, "['‘’‚‹›]")
        regexp.gsub!(/["“”„«»]/, '["“”„«»]')
        regexp.gsub!(/(?:\\\.\\\.\\\.|…)/, '(?:\.\.\.|…)')

        as_string ? regexp : /#{regexp}/i
      end

      def search(locale, query)
        results = {}
        regexp = self.class.create_search_regexp(query)

        I18n.fallbacks[locale].each do |fallback|
          find_results(regexp, results, translations[fallback])
        end

        results
      end

      protected

      def find_results(regexp, results, translations, path = nil)
        return results if translations.blank?

        translations.each do |k_sym, v|
          k = k_sym.to_s
          key_path = path ? "#{path}.#{k}" : k
          if v.is_a?(String)
            unless results.has_key?(key_path)
              results[key_path] = v if key_path =~ regexp || v =~ regexp
            end
          elsif v.is_a?(Hash)
            find_results(regexp, results, v, key_path)
          end
        end
        results
      end

      # Support interpolation and pluralization of overrides by first looking up
      # the original translations before applying our overrides.
      def lookup(locale, key, scope = [], options = {})
        existing_translations = super(locale, key, scope, options)
        return existing_translations if scope.is_a?(Array) && scope.include?(:models)

        overrides = options.dig(:overrides, locale)

        if overrides
          if existing_translations && options[:count]
            remapped_translations =
              if existing_translations.is_a?(Hash)
                Hash[existing_translations.map { |k, v| ["#{key}.#{k}", v] }]
              elsif existing_translations.is_a?(String)
                Hash[[[key, existing_translations]]]
              end

            result = {}

            remapped_translations.merge(overrides).each do |k, v|
              result[k.split('.').last.to_sym] = v if k != key && k.start_with?(key.to_s)
            end
            return result if result.size > 0
          end

          return overrides[key] if overrides[key]
        end

        existing_translations
      end

    end
  end
end
