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

require 'contrast/utils/object_share'
require 'contrast/api/dtm.pb'
require 'contrast/api/settings.pb'

module Contrast
  module Agent
    module Reporting
      # This module will hold all the settings from the TS responce
      module Settings
        # Application level settings for the Protect featureset
        class Protect
          # block at perimeter needs to be check against the blockAtEntry boolean value
          PROTECT_RULES_MODE = %w[OFF MONITORING BLOCKING].cs__freeze
          # The settings for each protect rule for this application
          #
          # @return protection_rules [Array<protectRule>] protectRule: {
          #   blockAtEntry [Boolean] If in block mode, to block at perimeter or not.
          #   id           [String] The id of a rule in Contrast.
          #   mode         [String] The mode that this rule should run in. [OFF, MONITORING, BLOCKING] }
          def protection_rules
            @_protection_rules ||= []
          end

          # Set the protection_rules array
          #
          # @param protection_rules [Array<protectRule>] protectRule: {
          #   blockAtEntry [Boolean] If in block mode, to block at perimeter or not.
          #   id           [String] The id of a rule in Contrast.
          #   mode         [String] The mode that this rule should run in. [OFF, MONITORING, BLOCKING] }
          # @return protection_rules [Array<protectRule>] protectRule: {
          #   blockAtEntry [Boolean] If in block mode, to block at perimeter or not.
          #   id           [String] The id of a rule in Contrast.
          #   mode         [String] The mode that this rule should run in. [OFF, MONITORING, BLOCKING] }
          def protection_rules= protection_rules
            @_protection_rules = protection_rules if protection_rules.is_a?(Array)
          end

          # The virtual patches to apply for this application
          #
          # @return virtual_patches [Array<VirtualPatch>] Array of VirtualPatch: {
          #   name       [String] The name of the Virtual Patch
          #   headers    [Array] The headers that must be present in the request to result in the request being blocked
          #   parameters [Array] The parameters that must be present in the request
          #                       to result in the request being blocked.
          #   urls       [Array] The urls that must be present in the request to result in the request being blocked.
          #   uuids      [String] The UUID of the Virtual Patch }
          def virtual_patches
            @_virtual_patches ||= []
          end

          # Set the virtual patches array
          #
          # @param virtual_patches [Array<VirtualPatch>] Array of VirtualPatch: {
          #   name       [String] The name of the Virtual Patch
          #   headers    [Array] The headers that must be present in the request to result in the request being blocked
          #   parameters [Array] The parameters that must be present in the request
          #                       to result in the request being blocked.
          #   urls       [Array] The urls that must be present in the request to result in the request being blocked.
          #   uuids      [String] The UUID of the Virtual Patch }
          # @return virtual_patches [Array<VirtualPatch>] Array of VirtualPatch: {
          #   name       [String] The name of the Virtual Patch
          #   headers    [Array] The headers that must be present in the request to result in the request being blocked
          #   parameters [Array] The parameters that must be present in the request
          #                       to result in the request being blocked.
          #   urls       [Array] The urls that must be present in the request to result in the request being blocked.
          #   uuids      [String] The UUID of the Virtual Patch }
          def virtual_patches= virtual_patches
            @_virtual_patches = virtual_patches if virtual_patches.is_a?(Array)
          end

          # Converts settings into Agent Settings understandable hash {RULE_ID => MODE}
          #
          # @return rules [Hash<RULE_ID => MODE>, nil] Hash with rule_id as key and mode as value
          def protection_rules_to_settings_hash
            return {} if protection_rules.empty?

            modes_by_id = {}
            protection_rules.each do |rule|
              setting_mode = rule[:mode]
              next unless PROTECT_RULES_MODE.include?(setting_mode)

              api_mode = case setting_mode
                         when PROTECT_RULES_MODE[1]
                           ::Contrast::Api::Settings::ProtectionRule::Mode::MONITOR
                         when PROTECT_RULES_MODE[2]
                           if rule[:blockAtEntry]
                             ::Contrast::Api::Settings::ProtectionRule::Mode::BLOCK_AT_PERIMETER
                           else
                             ::Contrast::Api::Settings::ProtectionRule::Mode::BLOCK
                           end
                         else
                           ::Contrast::Api::Settings::ProtectionRule::Mode::NO_ACTION
                         end

              modes_by_id[rule[:id]] = api_mode
            end
            modes_by_id
          end
        end
      end
    end
  end
end