# Copyright (c) 2023 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
# frozen_string_literal: true

module Contrast
  module Agent
    module Reporting
      module Settings
        # Helper methods used across the settings.
        module Helpers
          class << self
            # Known exclusion, we need different result, or just memo the output,
            # saving computing time. Reason to exist: different endpoints require different
            # attributes.
            NO_MORE_UNDERSCORE_EXCLUSIONS = {
                protect_rules: :rules,
                assess_rules: :assessmentRules,
                match_strategy: :matchStrategy
            }.cs__freeze

            # Fills instance variable [Array] with new settings as new instance type
            # for each entry.
            #
            # @param instance_type [Class] a class to create new instance from to
            # @param instance_variable [Array] instance variable accessor method
            # return an array to fill.
            # @param array [Array] array to be used to fill the iv.
            # fill the iv with the new type containing data from the provided array
            # param.
            # @param ng_endpoint [Boolean]
            # @return instance_variable [Class]
            def array_to_iv instance_type, instance_variable, array, ng_endpoint: false
              return unless array.is_a?(Array)

              # If we have a ng endpoint we have passed a boolean flag as param to the setter for the
              # array, and we need to retrieve the original array.
              payload = if ng_endpoint
                          array[0]
                        else
                          array
                        end

              payload.each_with_index do |entry, index|
                new_instance = instance_type.new
                instance_type::ATTRIBUTES.each do |attr|
                  key = ng_attribute_filter(attr, ng_endpoint: ng_endpoint)
                  new_instance.send("#{ attr }=".to_sym, entry[key])
                end
                instance_variable[index] = new_instance
              end

              instance_variable
            end

            # :attr_name => :attrName
            # return original if no '_'
            #
            # @param attr_name [Symbol]
            # @return normalized_name [Symbol, nil]
            def no_more_underscore attr_name
              name = attr_name.to_s
              idx = name.index('_')
              return attr_name if idx.nil? || (idx.zero? && idx >= name.length)

              result = name
              result.slice!(idx)
              result.insert(idx, name[idx]&.upcase)
              result.slice!(idx + 1)
              result.index('_') ? no_more_underscore(result).to_sym : result.to_sym
            end

            # Ng endpoints payload is different for exclusions.
            # This method will filter the attributes needed for each
            # each endpoint.
            #
            # @param attr_name [Symbol]
            # @param ng_endpoint [Boolean]
            # @return [Symbol, nil]
            def ng_attribute_filter attr_name, ng_endpoint: false
              if NO_MORE_UNDERSCORE_EXCLUSIONS.key?(attr_name)
                return NO_MORE_UNDERSCORE_EXCLUSIONS[attr_name] if ng_endpoint

                return attr_name
              end

              no_more_underscore(attr_name)
            end

            # rule_id => rule-id
            #
            # @param id [String, Symbol]
            def to_rule_id id
              return Contrast::Utils::ObjectShare::EMPTY_STRING unless id.cs__is_a?(String) || id.cs__is_a?(Symbol)

              id.to_s.downcase.tr('_', '-')
            end
          end
        end
      end
    end
  end
end