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

require 'contrast/agent/reporting/settings/code_exclusion'
require 'contrast/agent/reporting/settings/input_exclusion'
require 'contrast/agent/reporting/settings/url_exclusion'
require 'contrast/agent/reporting/settings/helpers'

module Contrast
  module Agent
    module Reporting
      # This module will hold all the settings from the TS responce
      module Settings
        # Application level settings for the Exclusions featureset
        # (ApplicationStartupSettingsExclusions)
        class Exclusions
          # Cases where rules should be excluded if violated in a method call
          #
          # @return code_exclusions [Array<Contrast::Agent::Reporting::Settings::CodeExclusion>] Array of CodeExclusion
          def code_exclusions
            @_code_exclusions ||= []
          end

          # set the CodeExclusions array
          #
          # @param new_code_exclusions [Array<CodeExclusion>] Array of CodeExclusion: {
          #   name         [String] The name of the exclusion as defined by the user in TS.
          #   modes        [String] If this exclusion applies to assess or protect. [assess, defend]
          #   assess_rules [Array] Array of assess rules to which this exclusion applies. AssessRuleID [String]
          #   denylist     [String] The call, if in the stack, should result in the agent not taking action.
          # }
          # @return code_exclusions [Array<Contrast::Agent::Reporting::Settings::CodeExclusion>] Array of CodeExclusion
          def code_exclusions= new_code_exclusions
            @_code_exclusions = Contrast::Agent::Reporting::Settings::Helpers.array_to_iv(
                Contrast::Agent::Reporting::Settings::CodeExclusion,
                code_exclusions,
                new_code_exclusions)
          end

          # Cases where rules should be excluded if violated from a given input.
          #
          # @return input_exclusions [Array<Contrast::Agent::Reporting::Settings::InputExclusions>]
          # Array of InputExclusions
          def input_exclusions
            @_input_exclusions ||= []
          end

          # set the InputExclusions array
          #
          # @param new_input_exclusions [Array<InputExclusions>] Array of InputExclusions: {
          #   name           [String] The name of the input.
          #   modes          [String] If this exclusion applies to assess or protect. [assess, defend]
          #   assess_rules   [Array] Array of assess rules to which this exclusion applies. AssessRuleID [String]
          #   protect_rules  [Array] Array of ProtectRuleID [String] The protect rules to which this exclusion applies.
          #   urls           [Array] Array of URLs to which the exclusions apply. URL [String]
          #   match_strategy [String] If this exclusion applies to all URLs or only those specified. [ALL, ONLY]
          #   type           [String] The type of the input [COOKIE, PARAMETER, HEADER, BODY, QUERYSTRING]
          # }
          # @return input_exclusions [Array<Contrast::Agent::Reporting::Settings::InputExclusions>]
          # Array of InputExclusions
          def input_exclusions= new_input_exclusions
            @_input_exclusions = Contrast::Agent::Reporting::Settings::Helpers.array_to_iv(
                Contrast::Agent::Reporting::Settings::InputExclusion,
                input_exclusions,
                new_input_exclusions)
          end

          # A case where rules should be excluded if violated during a call to a given URL.
          #
          # @return url_exclusions [Array<Contrast::Agent::Reporting::Settings::UrlExclusion>] Array of UrlExclusions
          def url_exclusions
            @_url_exclusions ||= []
          end

          # set the UrlExclusions array
          #
          # @param new_url_exclusions [Array] Array of UrlExclusions: {
          #   name           [String] The name of the input.
          #   modes          [String] If this exclusion applies to assess or protect. [assess, defend]
          #   assess_rules   [Array] Array of assess rules to which this exclusion applies. AssessRuleID [String]
          #   protect_rules  [Array] Array of ProtectRuleID [String] The protect rules to which this exclusion applies.
          #   urls           [Array] Array of URLs to which the exclusions apply. URL [String]
          #   match_strategy [String] If this exclusion applies to all URLs or only those specified. [ALL, ONLY]
          #   type           [String] The type of the input [COOKIE, PARAMETER, HEADER, BODY, QUERYSTRING]
          # }
          # @return url_exclusions [Array<Contrast::Agent::Reporting::Settings::UrlExclusion>] Array of UrlExclusions
          def url_exclusions= new_url_exclusions
            @_url_exclusions = Contrast::Agent::Reporting::Settings::Helpers.array_to_iv(
                Contrast::Agent::Reporting::Settings::UrlExclusion,
                url_exclusions,
                new_url_exclusions)
          end

          def to_controlled_hash
            {
                codeExceptions: code_exclusions.map(&:to_controlled_hash),
                inputExceptions: input_exclusions.map(&:to_controlled_hash),
                urlExceptions: url_exclusions.map(&:to_controlled_hash)
            }
          end
        end
      end
    end
  end
end