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

require 'contrast/components/base'

module Contrast
  module Components
    module Sampling
      module Constants
        DEFAULT_SAMPLING_ENABLED            = false
        DEFAULT_SAMPLING_BASELINE           = 5
        DEFAULT_SAMPLING_REQUEST_FREQUENCY  = 5
        DEFAULT_SAMPLING_RESPONSE_FREQUENCY = 25
        DEFAULT_SAMPLING_WINDOW_MS          = 180_000
      end

      module ClassMethods # :nodoc:
        include Contrast::Components::ComponentBase
        include Constants

        def sampling_enabled?
          sampling_control[:enabled]
        end

        def sampling_control
          @_sampling_control ||= begin
            config_settings = ::Contrast::CONFIG.root.assess&.sampling
            settings = ::Contrast::SETTINGS&.assess_state&.sampling_settings
            {
                enabled: enabled?(config_settings, settings),
                baseline: baseline(config_settings, settings),
                request_frequency: request_frequency(config_settings, settings),
                response_frequency: response_frequency(config_settings, settings),
                window: window(config_settings, settings)
            }
          end
        end

        # Used to reset sampling when settings from TeamServer change
        def reset_sampling_control
          @_sampling_control = nil
        end

        private

        # @param config_settings [Contrast::Config::SamplingConfiguration] the Sampling configuration as provided by
        #   local user input
        # @param settings [Contrast::Api::Settings::Sampling] the Sampling settings as provided by TeamServer
        # @return [Boolean] the resolution of the config_settings, settings, and default value
        def enabled? config_settings, settings
          true?([config_settings&.enable, settings&.enabled, DEFAULT_SAMPLING_ENABLED].compact[0])
        end

        # @param config_settings [Contrast::Config::SamplingConfiguration] the Sampling configuration as provided by
        #   local user input
        # @param settings [Contrast::Api::Settings::Sampling] the Sampling settings as provided by TeamServer
        # @return [Integer] the resolution of the config_settings, settings, and default value
        def baseline config_settings, settings
          [config_settings&.baseline, settings&.baseline].map(&:to_i).find(&:positive?) || DEFAULT_SAMPLING_BASELINE
        end

        # @param config_settings [Contrast::Config::SamplingConfiguration] the Sampling configuration as provided by
        #   local user input
        # @param settings [Contrast::Api::Settings::Sampling] the Sampling settings as provided by TeamServer
        # @return [Integer] the resolution of the config_settings, settings, and default value
        def request_frequency config_settings, settings
          [config_settings&.request_frequency, settings&.request_frequency].map(&:to_i).find(&:positive?) ||
              DEFAULT_SAMPLING_REQUEST_FREQUENCY
        end

        # @param config_settings [Contrast::Config::SamplingConfiguration] the Sampling configuration as provided by
        #   local user input
        # @param settings [Contrast::Api::Settings::Sampling] the Sampling settings as provided by TeamServer
        # @return [Integer] the resolution of the config_settings, settings, and default value
        def response_frequency config_settings, settings
          [config_settings&.response_frequency, settings&.response_frequency].map(&:to_i).find(&:positive?) ||
              DEFAULT_SAMPLING_RESPONSE_FREQUENCY
        end

        # @param config_settings [Contrast::Config::SamplingConfiguration] the Sampling configuration as provided by
        #   local user input
        # @param settings [Contrast::Api::Settings::Sampling] the Sampling settings as provided by TeamServer
        # @return [Integer] the resolution of the config_settings, settings, and default value
        def window config_settings, settings
          [config_settings&.window_ms, settings&.window_ms].map(&:to_i).find(&:positive?) || DEFAULT_SAMPLING_WINDOW_MS
        end
      end

      module InstanceMethods # :nodoc:
        include Contrast::Components::ComponentBase
        include Constants
        include ClassMethods
      end
    end
  end
end