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

require 'contrast/utils/string_utils'
require 'contrast/utils/assess/tracking_util'
require 'base64'
require 'contrast/components/scope'

module Contrast
  module Api
    module Decorators
      # Used to decorate the {Contrast::Api::Dtm::TraceEventObject} protobuf
      # model.
      module TraceEventObject
        def self.included klass
          klass.extend(ClassMethods)
        end

        # Class methods for TraceEventObject
        module ClassMethods
          include Contrast::Components::Scope::InstanceMethods
          # Build the event object. We were originally going to include taint on
          # each one, but TS doesn't accept / use that, so it is a waste of time.
          #
          # We'll truncate any object that isn't important to the taint ranges of
          # this event, so that we don't murder TeamServer by, for instance,
          # hypothetically sending the entire rendered HTML page >_>  <_<  >_>
          ELLIPSIS = '...'
          UNTRUNCATED_PORTION_LENGTH = 25
          TRUNCATION_LENGTH = (UNTRUNCATED_PORTION_LENGTH * 2) + ELLIPSIS.length

          # Convert the given Object into a Contrast::Api::Dtm::TraceEventObject
          #
          # @param contrast_object [Contrast::Agent::Assess::ContrastObject, nil]
          #   the thing to convert, if any
          # @param truncate [Boolean] if the converted object can/should be
          #   truncated.
          # @return [Contrast::Api::Dtm::TraceEventObject]
          def build contrast_object, truncate
            event_object = new
            with_contrast_scope do
              obj_string = Contrast::Utils::StringUtils.force_utf8(contrast_object&.object)
              obj_string = truncate(obj_string) if truncate && obj_string.length > TRUNCATION_LENGTH
              event_object.value = Base64.encode64(obj_string)
              event_object.tracked = contrast_object&.tracked?
            end
            event_object
          end

          def truncate obj_string
            tmp = []
            tmp << obj_string[0, UNTRUNCATED_PORTION_LENGTH]
            tmp << ELLIPSIS
            tmp << obj_string[obj_string.length - UNTRUNCATED_PORTION_LENGTH, UNTRUNCATED_PORTION_LENGTH]
            tmp.join
          end
        end
      end
    end
  end
end

Contrast::Api::Dtm::TraceEventObject.include(Contrast::Api::Decorators::TraceEventObject)