#!/usr/bin/env ruby

require "time"
require "thread"
require "history_client"

module PerformanceTest
  class AddAudits
    attr_accessor :aws_client, :threads_count, :audits_count, :counter_mutex, :counter, :log_mutex

    DEFAULT_EXPIRY= 60 * 60 * 24 * 365 # 1 year
    SERVICE_ENDPOINT = "http://history.staging.us-west2.twitch.tv"

    RESOURCES = %w(twitch_user channel app_settings vod notification)
    ACTIONS = %w(create read update delete)
    ATTRIBUTES = %w(login birthday bio image)
    VALUES = (1..20).map { |i| "test#{i}" }
    IDS = (1..100).to_a

    def initialize(args = [])
      @threads_count = [args[0].to_i, 1].max
      @audits_count = [args[1].to_i, 1].max
      @aws_client = History::Client.new("endpoint" => SERVICE_ENDPOINT)
      @log_mutex = Mutex.new
      @counter_mutex = Mutex.new
      @counter = 0
    end

    def dummy_audit
      audit = History::Audit.new
      audit.created_at = Time.now.utc.round(3).iso8601(3)
      audit.expiry = DEFAULT_EXPIRY
      audit.action = ACTIONS.sample
      audit.resource_type = RESOURCES.sample
      audit.resource_id = IDS.sample
      audit.user_type = "performance_tester"
      audit.user_id = "1"
      audit.description = next_count

      change = History::ChangeSet.new
      change.attribute = ATTRIBUTES.sample
      change.old_value = VALUES.sample
      change.new_value = (VALUES - [change.old_value]).sample
      audit.changes = [change]

      audit
    end

    def add_audits(audits_count, thread_number)
      audits_count.times do |i|
        log thread_number, i
        begin
          aws_client.add(dummy_audit)
        rescue => e
          log thread_number, i, e.message
        end
        wait
      end
    end

    def wait
      sleep rand
    end

    def next_count
      @counter_mutex.synchronize do
        @counter += 1
      end
    end

    def log(thread_number, audit_number, message = nil)
      @log_mutex.synchronize do
        puts ["Thread(#{thread_number + 1}) adding audit(#{audit_number + 1})", message].compact.join(" => ")
      end
    end

    def run
      threads = []

      threads_count.times do |i|
        threads << Thread.new do
          add_audits(audits_count, i)
        end
      end

      threads.each &:join
    end
  end
end

performance_test = PerformanceTest::AddAudits.new(ARGV)
performance_test.run
