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

require 'contrast/config/diagnostics/tools'
require 'contrast/utils/object_share'
require 'contrast/utils/duck_utils'

module Contrast
  module Components
    # All components should inherit from this,
    # whether Interfaces, InstanceMethods or ClassMethods.
    module ComponentBase
      include Contrast::Config::Diagnostics::Tools

      ENABLE = 'enable'

      # Used for config diagnostics. Override per rule.
      #
      # @return [String]
      def canon_name
        Contrast::Utils::ObjectShare::EMPTY_STRING
      end

      # Used for config diagnostics. Override per rule.
      #
      # @return [Array]
      def config_values
        Contrast::Utils::ObjectShare::EMPTY_ARRAY
      end

      # use this to determine if the configuration value is literally boolean
      # false or some form of the word `false`, regardless of case. It should
      # be used for those values which default to `true` as they should only
      # treat a value explicitly set to `false` as such.
      #
      # @param config_param [Boolean,String] the value to check
      # @return [Boolean] should the value be treated as `false`
      def false? config_param
        return false if config_param == true
        return true if config_param == false
        return false unless config_param.cs__is_a?(String)

        config_param.downcase == Contrast::Utils::ObjectShare::FALSE
      end

      # use this to determine if the configuration value is literally boolean
      # true or some form of the word `true`, regardless of case. It should
      # be used for those values which default to `false` as they should only
      # treat a value explicitly set to `true` as such.
      #
      # @param config_param [Boolean,String] the value to check
      # @return [Boolean] should the value be treated as `true`
      def true? config_param
        return false if config_param == false
        return true if config_param == true
        return false unless config_param.cs__is_a?(String)

        config_param.downcase == Contrast::Utils::ObjectShare::TRUE
      end

      # this method will check if a path could be possibly used
      # So for example if we pass a path to a file - we'll check
      # if there is actually that file and if it's with certain extension
      #
      # @param config_path [String,nil]
      # @return [Boolean]
      def valid_cert? config_path
        return false if config_path.nil?

        exts = %w[.pem .crt .cer].cs__freeze
        return false unless exts.include?(File.extname(config_path))

        true
      end

      # check if file exists at all
      # @param path [String,nil]
      def file_exists? path
        return false unless path

        File.exist?(path)
      end

      # Converts current configuration to effective config values class and appends them to
      # EffectiveConfig class.
      #
      # @param effective_config [Contrast::Config::Diagnostics::EffectiveConfig]
      def to_effective_config effective_config
        add_effective_config_values(effective_config, config_values, canon_name)
      end

      # attempts to stringify the config value if it is an array with the join char
      #
      # @param val[Object] val to stringify
      # @param join_char[String, ','] join character defaults to ','
      # @return [String, Object] the stringified val or the object as is
      def stringify_array val, join_char = ','
        return val.join(join_char) if val.cs__is_a?(Array) && val.any?

        val
      end
    end
  end
end