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

require 'contrast/api/dtm.pb'
require 'contrast/components/logger'

module Contrast
  module Agent
    module Reporting
      # This is the new Architecture Component class which will include all the needed information for the new
      # reporting system to relay this information in the Application Update and Application Activity messages. These
      # components are used by TeamServer to construct the backend/ outbound connection section of the Flow Map
      # feature.
      #
      # @attr_reader remote_host [String] the host section of the connection to the component.
      # @attr_reader remote_port [Integer] the port section of the connection to the component.
      # @attr_reader type [String] the type of the component. Only ::VALID_TYPES can be used. Required for reporting.
      # @attr_reader url [String] the url used to connect to the component. Required for reporting.
      # @attr_reader vendor [String] the publisher of the component, like MySQL.
      class ArchitectureComponent
        include Contrast::Components::Logger::InstanceMethods
        # required attributes
        attr_reader :type, :url
        # optional attributes
        attr_reader :remote_host, :remote_port, :vendor

        # TeamServer only treats these specific values as valid for Architecture Components. It does not know how to
        # process a message with a different type.
        VALID_TYPES = %w[db ldap ws].cs__freeze

        class << self
          # Convert a DTM for SpeedRacer to an Event for TeamServer.
          #
          # @param component_dtm [Contrast::Api::Dtm::ArchitectureComponent]
          # @return [Contrast::Agent::Reporting::ArchitectureComponent]
          def convert component_dtm
            report = new
            report.attach_data(component_dtm)
            report
          end
        end

        # Attach the data from the protobuf models to this reporter so that it can be sent to TeamServer directly.
        #
        # @param component_dtm [Contrast::Api::Dtm::ArchitectureComponent]
        def attach_data component_dtm
          @remote_host = component_dtm.remote_host
          @remote_port = component_dtm.remote_port
          @type = component_dtm.type
          @url = component_dtm.url
          @vendor = component_dtm.vendor
        end

        # Convert the instance variables on the class, and other information, into the identifiers required for
        # TeamServer to process the JSON form of this message.
        #
        # @return [Hash]
        # @raise [ArgumentError]
        def to_controlled_hash
          begin
            validate
          rescue ArgumentError => e
            logger.error('ArchitectureComponent validation failed with: ', e)
            return
          end
          {
              remoteHost: remote_host,
              remotePort: remote_port,
              type: type,
              url: url,
              vendor: vendor
          }
        end

        # Ensure the required fields are present.
        #
        # @raise [ArgumentError]
        def validate
          unless VALID_TYPES.include?(type)
            raise(ArgumentError, "#{ self } did not have a proper type - '#{ type }'. Unable to continue.")
          end
          raise(ArgumentError, "#{ self } did not have a proper URL. Unable to continue.") unless url
        end
      end
    end
  end
end