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

require 'contrast/agent/assess/finalizers/hash'

module Contrast
  module Agent
    module Assess
      # How we track the Assess properties attached to objects
      #
      # Finalized objects should run through this class as the Finalizers
      # have tightly coupled dependencies on each other.
      class Tracker
        PROPERTIES_HASH = Contrast::Agent::Assess::Finalizers::Hash.new

        class << self
          # Retrieve the properties of the given Object, iff they exist.
          #
          # @param source [Object, nil] the thing for which to look up properties.
          # @return [Contrast::Agent::Assess::Properties, nil]
          def properties source
            PROPERTIES_HASH[source]
          end

          # Retrieve the properties of the given Object, returning a new
          # instance if one does not already exist and the source is trackable.
          #
          # @param source [Object] the thing for which to look up properties.
          # @return [Contrast::Agent::Assess::Properties, nil]
          def properties! source
            return unless trackable?(source)

            PROPERTIES_HASH[source] ||= Contrast::Agent::Assess::Properties.new
          end

          def trackable? source
            PROPERTIES_HASH.trackable?(source)
          end

          def tracked? source
            PROPERTIES_HASH.tracked?(source)
          end

          def pre_freeze source
            PROPERTIES_HASH.pre_freeze(source)
          end

          # Copy the properties from one object to the next, assuming the
          # target does not already have its own properties. This should only
          # ever be called when building PreShift for those objects sources
          # which are already tracked.
          #
          # @param source [Object] the instance from which to copy properties
          # @param target [Object] the instance to which to copy properties
          def copy source, target
            PROPERTIES_HASH[target] ||= properties(source).dup
          end
        end
      end
    end
  end
end

require 'contrast/agent/assess/finalizers/freeze'