require 'bundler'
require 'pry'
require 'fileutils'
require 'rcs-common'
require 'rcs-common/mongoid'
require 'rcs-common/trace'
require 'rcs-common/path_utils'

# require customer rspec matchers
require File.expand_path 'spec_matchers', File.dirname(__FILE__)

# require factory framework
require File.expand_path 'spec_factories', File.dirname(__FILE__)

require_relative 'stubs/tracer'
require_relative 'stubs/mongoid'
require_relative 'stubs/archive_server'

$execution_directory = File.expand_path('../..', __FILE__)

# Define global before and each proc
RSpec.configure do |config|
  config.mock_with :rspec do |c|
    c.syntax = [:should, :expect]
  end

  # * Clean up the spec_temp_folder
  # * Connecto to mongodb
  config.before(:all) do
    mongo_setup
    empty_test_db
  end

  config.before(:each) do
    # Silence deprecation warning
    I18n.enforce_available_locales = false if defined?(I18n)

    RCS::DB::Config.instance.stub(:temp_folder_name).and_return 'temp/.spec'
    empty_temp_folder

    turn_off_tracer

    empty_test_db unless @disable_mongoid_purge
  end

  config.after(:all) do
    empty_temp_folder
  end
end

def empty_temp_folder
  FileUtils.rm_rf(RCS::DB::Config.instance.temp)
  FileUtils.mkdir_p(RCS::DB::Config.instance.temp)
end

def spec_temp_folder(subpath = nil)
  RCS::DB::Config.instance.temp(subpath)
end

def fixtures_path(subpath = nil)
  @fixtures_path ||= File.join(File.dirname(__FILE__), 'fixtures')
  subpath && File.join(@fixtures_path, subpath) || @fixtures_path
end

def rcs_require(relative_path, file)
  relative_path_file = File.join(Dir.pwd, relative_path, file)
  require_release(relative_path_file)
end

def require_db(file)
  rcs_require('lib/rcs-db/', file)
end

def require_aggregator(file)
  rcs_require('lib/rcs-aggregator/', file)
end

def require_intelligence(file)
  rcs_require('lib/rcs-intelligence/', file)
end

def require_ocr(file)
  rcs_require('lib/rcs-ocr/', file)
end

def require_worker(file)
  rcs_require('lib/rcs-worker/', file)
end

def require_connector(file)
  rcs_require('lib/rcs-connector/', file)
end

def require_monitor(file)
  rcs_require('lib/rcs-monitor/', file)
end

# Setup mongoid.
# Simulate a sharded enviroments
def mongo_setup
  Mongoid.load!('config/mongoid.yaml', :production)

  admin_db = Mongoid.default_session.with(database: 'admin')
  shard_list = admin_db.command(listshards: 1)['shards']
  admin_db.command(addshard: "#{ENV['MONGOID_HOST']}:27018") if shard_list.empty?
  admin_db.command(enablesharding: ENV['MONGOID_DATABASE']) rescue nil
end

def empty_test_db
  Mongoid.purge!
  Mongoid.default_session.with(database: 'rcs-worker-test').collections.map &:drop
end

def do_not_empty_test_db
  @disable_mongoid_purge = true
end

# Check out RCS::Tracer module of rcs-common gem
def turn_off_tracer(opts = {})
  Log4r::Logger.stub(:[]).and_return(RCS::Stubs.logger(opts))
end

def turn_on_tracer
  Log4r::Logger.stub(:[]).and_return(nil)
end

# Stub the LicenseManager instance to simulate the presence of a valid license
def enable_license
  before do
    eval 'class LicenseManager; end' unless defined? LicenseManager
    LicenseManager.stub(:instance).and_return double()
    LicenseManager.instance.stub(:check).and_return true
    LicenseManager.instance.stub(:can_build_platform).and_return true
  end
end

# Stub all the methods that send alerts or push notification to the console
def silence_alerts
  before do
    Entity.any_instance.stub :alert_new_entity
    Entity.any_instance.stub :push_notify
    RCS::DB::LinkManager.any_instance.stub :alert_new_link
  end
end

# Restore a file created with mongodump
# Assumes that the dump file is located in the fixture folder (spec/fixtures)
def mongorestore(path)
  path = File.expand_path File.join(fixtures_path, path)
  return unless File.exists? path
  empty_test_db
  cmd = "mongorestore \"#{path}\""
  puts cmd
  `#{cmd}`
end

def evidence_no_conflict
  before(:each) do
    load('rcs-common/evidence.rb') unless defined?(RCS::Evidence)
  end

  after(:all) do
    # Remove the RCS::Evidence class defined by rcs-common/evidence
    RCS.send(:remove_const, 'Evidence') if defined?(RCS::Evidence)
  end
end