class ForemanOpenscap::ArfReport

def self.bit_mask(status)

def self.bit_mask(status)
  ComplianceStatus.bit_mask(status)
end

def self.create_arf(asset, proxy, params)

def self.create_arf(asset, proxy, params)
  arf_report = nil
  policy = Policy.find_by :id => params[:policy_id]
  return unless policy
  ArfReport.transaction do
    arf_report = ArfReport.create(:host => asset.host,
                                  :reported_at => Time.at(params[:date].to_i),
                                  :status => params[:metrics],
                                  :metrics => params[:metrics],
                                  :openscap_proxy => proxy)
    return arf_report unless arf_report.persisted?
    PolicyArfReport.where(:arf_report_id => arf_report.id, :policy_id => policy.id, :digest => params[:digest]).first_or_create!
    if params[:logs]
      params[:logs].each do |log|
        src = Source.find_or_create_by(value: log[:source])
        msg = nil
        if src.logs.count > 0
          msg = Log.where(:source_id => src.id).order(:id => :desc).first.message
          update_msg_with_changes(msg, log)
        else
          if (msg = Message.find_by(:value => log[:title]))
            msg.attributes = {
              :value => N_(log[:title]),
              :severity => log[:severity],
              :description => newline_to_space(log[:description]),
              :rationale => newline_to_space(log[:rationale]),
              :scap_references => references_links(log[:references]),
              :fixes => fixes(log[:fixes])
            }
          else
            msg = Message.new(:value => N_(log[:title]),
                              :severity => log[:severity],
                              :description => newline_to_space(log[:description]),
                              :rationale => newline_to_space(log[:rationale]),
                              :scap_references => references_links(log[:references]),
                              :fixes => fixes(log[:fixes]))
          end
          msg.save!
        end
        # TODO: log level
        Log.create!(:source_id => src.id,
                    :message_id => msg.id,
                    :level => :info,
                    :result => log[:result],
                    :report => arf_report)
      end
    end
  end
  arf_report
end

def self.fixes(raw_fixes)

def self.fixes(raw_fixes)
  return if raw_fixes.empty?
  JSON.fast_generate(raw_fixes)
end

def self.newline_to_space(string)

def self.newline_to_space(string)
  string.gsub(/ *\n+/, " ")
end

def self.references_links(references)

def self.references_links(references)
  return if references.nil?
  html_links = []
  references.each do |reference|
    next if reference['title'] == 'test_attestation' # A blank url created by OpenSCAP
    reference['html_link'] = "<a href='#{reference['href']}'>#{reference['href']}</a>" if reference['title'].blank?
    html_links << reference['html_link']
  end
  html_links.join(', ')
end

def self.report_status_column

def self.report_status_column
  "status"
end

def self.update_msg_with_changes(msg, incoming_data)

def self.update_msg_with_changes(msg, incoming_data)
  msg.severity = incoming_data['severity']
  msg.description = incoming_data['description']
  msg.rationale = incoming_data['rationale']
  msg.scap_references = incoming_data['references']
  msg.value = incoming_data['title']
  msg.fixes = fixes(incoming_data['fixes'])
  return unless msg.changed?
  msg.save
end

def assign_locations_organizations

def assign_locations_organizations
  if host
    self.location_ids = [host.location_id]
    self.organization_ids = [host.organization_id]
  end
end

def calculator

def calculator
  ArfReportStatusCalculator.new(:bit_field => read_attribute(self.class.report_status_column))
end

def destroy_from_proxy

def destroy_from_proxy
  if !host
    destroy_from_proxy_warning "host"
  elsif !policy
    destroy_from_proxy_warning "policy"
  elsif !openscap_proxy
    destroy_from_proxy_warning "OpenSCAP proxy"
  else
    openscap_proxy_api.destroy_report(self, ForemanOpenscap::Helper::find_name_or_uuid_by_host(host))
  end
end

def destroy_from_proxy_warning(associated)

def destroy_from_proxy_warning(associated)
  logger.warn "Skipping deletion of report with id #{id} from proxy, no #{associated} associated with report"
  true
end

def equal?(other)

def equal?(other)
  results = [logs, other.logs].flatten.group_by(&:source_id).values
  # for each rule, there should be one result from both reports
  return false unless results.map(&:length).all? { |item| item == 2 }
  results.all? { |result| result.first.source_id == result.last.source_id } &&
    host_id == other.host_id &&
    policy.id == other.policy.id
end

def failed

def failed
  status_of "failed"
end

def failed?

def failed?
  failed > 0
end

def othered

def othered
  status_of "othered"
end

def othered?

def othered?
  !passed? && !failed?
end

def passed

def passed
  status_of "passed"
end

def passed?

def passed?
  passed > 0 && failed == 0 && othered == 0
end

def rules_count

def rules_count
  status.values.sum
end

def status=(st)

def status=(st)
  s = case st
      when Integer
        st
      when Hash, ActionController::Parameters
        ArfReportStatusCalculator.new(:counters => st).calculate
      else
        raise "Unsupported report status format #{st.class}"
      end
  write_attribute(:status, s)
end

def to_bzip

def to_bzip
  openscap_proxy_api.arf_report_bzip(self, ForemanOpenscap::Helper::find_name_or_uuid_by_host(host))
end

def to_html

def to_html
  openscap_proxy_api.arf_report_html(self, ForemanOpenscap::Helper::find_name_or_uuid_by_host(host))
end