# -*- encoding : utf-8 -*-

class RailsInflectionUpdates < Cardio::Migration::Transform
  def word ar
    [/(?<=\W|_|^)#{ar[0]}(?=\W|_|$)/i, /(?<=\W|_|^)#{ar[1]}(?=\W|_|$)/i, ar[2]]
  end

  def word_end ar
    [/#{ar[0]}(?=\W|_|$)/i, /#{ar[1]}(?=\W|_|$)/i, ar[2]]
  end

  def keep_the_s word
    ["#{word}s", word, "#{word}s"]
  end

  def unless_name_collision card
    if (twin = Card.find_by_key(card.name.key)) && twin.id != card.id
      if twin.trash
        twin.destroy
        yield
      elsif !card.trash
        unresolvable_name_collision! card, twin
      end
    else
      yield
    end
  end

  def unresolvable_name_collision! card, twin
    raise Card::Error::Oops,
          "Your deck has two different cards with names '#{card.name}' and " \
          "'#{twin.name}'. After this update it's no longer possible to " \
          "differentiate between those two names. Please rename or delete one of " \
          "the two cards and run the update again."
  end

  def up
    card_names = Card.pluck(:name)
    apply_to_content = ::Set.new
    corrections = [
      # plural,     wrong singular,  correct singular
      word(['(\w+)lice',  '(\w+)louse',    '\1lice']),
      word(['(\w+)mice',  '(\w+)mouse',    '\1mice']),
      word_end(%w[kine cow kine]),
      word(keep_the_s("analysi")),
      word(keep_the_s("axi"))
    ]
    %w[statu crisi alia bu octopu viru analysi basi diagnosi parenthesi
       prognosi synopsi thesi].each do |word|
      corrections << word_end(keep_the_s(word))
    end

    corrections.each_with_index do |cors, i|
      plural, wrong_sing, correct_sing = cors

      card_names.reject! do |name|  # change a name only once
        next unless name =~ plural

        # can't use fetch, because it uses the wrong key
        # find_by_name is case-insensitve and finds the wrong cards for camel case names
        card = Card.where(name: name).find { |card| card.name == name }

        unless_name_collision(card) do
          apply_to_content << i
          new_key = name.to_name.key
          if card.key == new_key
            # noop.  probably means this was already migrated?
          elsif Card.find_by_key new_key
            puts "Could not update #{name}. Key '#{new_key}' already exists."
          else
            card.update! key: new_key
          end
        end
      end
    end

    cards_with_css = Card.search type: %w[in html css scss]
    cards_with_css.each do |card|
      new_content = card.db_content
      content_changed = false

      apply_to_content.each do |i|
        plural, wrong_sing, correct_sing = corrections[i]
        if card.db_content =~ wrong_sing
          content_changed = true
          new_content = new_content.gsub(wrong_sing, correct_sing)
        end
      end
      card.update! content: new_content if content_changed
    end
  end
end
