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

require 'contrast/components/logger'

module Contrast
  module Extension
    # Our top level Assess namespace in the Core Extension section of our
    # code. These patches are those that are invoked directly from a patched
    # Class.
    #
    module Assess
      # This is the main instrument helper giving the method of requiring C patches
      #
      module InstrumentHelper
        class << self
          include Contrast::Components::Logger::InstanceMethods

          # Unites the different require methods into one, using only
          # the provided path for the C patches
          # parameters
          # @param path[String] Path to the required patch
          #
          def instrument path
            var_name, extracted_name = gen_name(path)
            return if instance_variable_get(var_name) == true

            instance_variable_set(var_name, assign_value(path))
          rescue StandardError, LoadError => e
            logger.error("Error loading #{ extracted_name&.nil? ? '' : extracted_name } patch", e)
            false
          end

          # Some of the requires have some extra conditions for them to require
          # the C patches, so this method is helping us move the logic by making some
          # conditions
          def assign_value path
            case path
            when /fiber/, /interpolation26/
              require(path) if Funchook.available?
            else
              require(path)
            end
            true
          end

          # Generate the needed instance variable name and return the extracted name
          def gen_name path
            extracted_name = path.split(%r{[\s_/]})&.uniq&.delete_if do |s|
              s.empty? || s == 'cs' || s == 'assess' || s == 'track'
            end
            extracted_name = (extracted_name&.length || 0) > 1 ? extracted_name&.join('_') : extracted_name&.pop
            ["@_instrument_#{ extracted_name }_track", extracted_name]
          end
        end
      end
    end
  end
end