#!/usr/bin/env ruby

#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++

if !defined? Rails
  puts "Loading necessary files to run without loading Rails"
  puts "(Alternatively, you can try running bundle exec rails runner #{$0})"
  puts

  require "pathname"
  require "yaml"
  require "active_support/core_ext/hash/deep_merge"
  require "active_support/core_ext/hash/keys"
  require "active_support/core_ext/object/blank"

  class Rails
    def self.root
      Pathname.new File.expand_path("../../", __dir__)
    end
  end

  module Source; end

  # order is important
  require Rails.root.join("app/seeders/source/translate.rb")
  require Rails.root.join("app/seeders/source/filter_translatables.rb")
  require Rails.root.join("app/seeders/source/seed_file.rb")
end

class GenerateSeederSourceTranslationFiles
  class << self
    include Source::FilterTranslatables

    def call
      Source::SeedFile.all
        .group_by { _1.path.dirname }
        .each do |dir, seed_files|
          create_crowdin_source_file(dir, seed_files)
        end
      create_additional_dummy_crowdin_source_file
      puts "Done"
    end

    def create_crowdin_source_file(dir, seed_files)
      source_data = translatable_data(seed_files)
      return if source_data.blank?

      source_file_path(dir).open("w") do |f|
        puts "Generate crowdin source file #{relative_path(f.path)}"

        f.puts comment
        YAML.dump(source_data, f)
      end
    end

    def create_additional_dummy_crowdin_source_file
      dummy_file = Rails.root.join("modules/boards/config/locales/en.seeders.yml")
      content = <<~CONTENT
        #{comment}
        #
        # This file is needed to prevent bug #48450: at least two 'en.seeders.yml' files
        # located in the modules directories are needed to have crowdin cli correctly
        # compute the path to the uploaded source file.
        #
        # This file does not contain any i18n strings.

        en:
      CONTENT
      File.write(dummy_file, content)

      puts "Generate additional dummy crowdin source file #{relative_path(dummy_file.to_s)}"
    end

    def source_file_path(seed_file_path)
      base_path = seed_file_path
      loop do
        base_path, dir = base_path.split
        break if dir.to_s == "app"
      end
      base_path.join("config/locales/en.seeders.yml")
    end

    def comment
      <<~COMMENT.freeze
        # This file has been generated by #{relative_path($0)}.
        # Please do not edit directly.
        #
        # This file is part of the sources sent to crowdin for translation.
      COMMENT
    end

    def translatable_data(seed_files)
      merged_translatables = seed_files.reduce({}) do |acc, seed_file|
        translatables = filter_translatables(seed_file.raw_content)
        next acc if translatables.blank?

        acc.deep_merge(seed_file.name => translatables)
      end
      return if merged_translatables.blank?

      {
        "en" => {
          Source::Translate::I18N_PREFIX => merged_translatables
        }
      }
    end

    def relative_path(path)
      return path unless path.start_with?("/")

      Pathname.new(path).relative_path_from(Rails.root).to_s
    end
  end
end

GenerateSeederSourceTranslationFiles.call
