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

require_relative 'base'

module Contrast
  module Agent
    module Telemetry
      module Exception
        # This class will hold the all the information for the specific exception
        # and will be passed in the Exception message itself
        class StackFrame < Contrast::Agent::Telemetry::Exception::Base
          VALIDATIONS = {
              function: { required: true, range: 1..256 },
              type: { required: true, range: 1..256 },
              module_name: { required: false, range: 1..256 }
          }.cs__freeze

          # @return [String] The type of the exception itself
          attr_reader :type

          # @return [String] the function of the stack trace
          attr_reader :function

          # @return [Boolean] Is it in contrast
          attr_accessor :in_contrast

          # @return [String]
          attr_reader :module_name

          # @raise [ArgumentError]
          def initialize function, type
            super()
            @function = function
            @type = type
            @in_contrast = false
            validate(VALIDATIONS)
          end

          # @raise [ArgumentError]
          def module_name= module_name
            @module_name = module_name
            validate_field(VALIDATIONS[:module_name], 'module_name')
          end

          # @raise [ArgumentError]
          def to_controlled_hash
            super
            { function: function, type: type, module: module_name, inContrast: in_contrast }.compact
          end

          class << self
            # @param method [String] method, triggered the logger on warn/error/fatal
            # @param type [String] the type ( where it occurred )
            # @param module_name [String, nil] Name of the module if any.
            def build method, type, module_name = nil
              inst = new(method, type)
              inst.module_name = module_name if module_name
              inst.in_contrast = type.include?('lib/contrast')
              inst
            end
          end
        end
      end
    end
  end
end