desc 'Extract and insert Translations for Glossync models' task setup_model_translations: :environment do

# eager load all the rails constants
Rails.application.eager_load!
# don't reload the I18n backend on each tl_update
Glossync.dont_reload_backend
# require 'io/console' so we can get the terminal's width
require 'io/console'

# a lambda to insert translations, returns true if a translation was inserted
# or false otherwise
insert_translation = lambda do |locale|
  lambda do |key, value|
    if Translation.exists?(key: key)
      false
    else
      Translation.create(locale: locale, key: key, value: value)
      true
    end
  end
end

# handy lambda to calculate percents
pct = ->(y) { ->(x) { (x * 100.0) / y } }

# lambda to display a pretty log of our progress
log = ->(m, i, t, pct, a) do
  graphw = ($stdout.winsize[1] - 70)
  printf(
    "\r[\e[35m%5.1f%%\e[0m] -- processing " +
      "\e[34m%-20.20s\e[0m (\e[35m%5d\e[0m/\e[37m%5d\e[0m) " +
      "\e[%sm%-8.8s\e[0m [\e[35m%-#{graphw}.#{graphw}s\e[0m]\e[K",
    pct, m.to_s, i + 1, t, a == 'skipping' ? '33' : '32', a,
    graphw.positive? ? ('#' * (graphw * pct / 100).round) : ''
  )
end

# setup the translation lambda to insert english translations
tl = insert_translation.('en')

# get a list of models that include Glossync
models = ActiveRecord::Base.descendants.select do |c|
  c.included_modules.include?(Glossync)
end

# setup some variables for displaying information
pct = pct.(models.map(&:count).reduce(0, :+))
x = 0
actions = { 'skipping' => 0, 'adding' => 0 }
start_time = Time.now

# this is the main logic of the task, for each model and each key within that
# model that is translatable, insert a new translation

# for each model that includes Glossync
models.each do |model|
  # get a list of the keys that module ``has_translations_for''
  keys = model.glossync
  # c is the number of instances of this particular model (used later in
  # printing the progress bar)
  c = model.count

  # for each instance of the model,
  model.all.each_with_index do |e, i|
    # for each key that has a translatoin call the above tl Proc an get an
    # array of bools indicating wether or not the translation was inserted or
    # skipped
    status = keys.map {|k| tl.(e.tl_key(k), e[k]) }

    # make a message indicating wether we added anything
    msg = status.any? ? 'adding' : 'skipping'

    # record the action count
    actions[msg] += 1

    # print some info
    log.(model, i, c, pct.(x += 1), msg)
  end
end

# print a summary
printf(
  "\r[\e[35m100.0%%\e[0m] -- done, " +
    "processed \e[35m%d\e[0m models " +
    "(\e[33mskipped %d\e[0m, \e[32madded %d\e[0m) " +
    "in \e[34m%.1f\e[0m seconds\e[K\n",
  x, actions['skipping'], actions['adding'], Time.now - start_time
)

end