module Mtx::IANALanguageSubtagRegistry
  @@registry_mutex = Mutex.new
  @@registry       = nil

  def self.fetch_registry
    @@registry_mutex.synchronize {
      return @@registry if @@registry

      shorten_description_for = %w{1959acad abl1943 ao1990 colb1945}
      @@registry              = {}
      entry                   = {}
      process                 = lambda do
        type = entry.delete(:type)

        if shorten_description_for.include? entry[:subtag]
          entry[:description].gsub!(%r{ +\(.*?\)}, '')
        end

        if type
          @@registry[type] ||= []
          @@registry[type]  << entry
        end

        entry = {}
      end

      current_sym             = nil

      Mtx::OnlineFile.download("https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry").
        split(%r{\n+}).
        map(&:chomp).
        each do |line|

        if line == '%%'
          process.call
          current_sym = nil

        elsif %r{^Prefix: *(.+)}i.match(line)
          entry[:prefix] ||= []
          entry[:prefix]  << $1
          current_sym      = nil

        elsif %r{^(.*?): *(.+)}i.match(line)
          current_sym        = $1.downcase.to_sym
          entry[current_sym] = $2

        elsif %r{^ +(.+)}.match(line) && current_sym
          entry[current_sym] += " #{$1}"

        end
      end

      process.call
    }

    return @@registry
  end

  def self.do_create_cpp entries
    cpp_file_name   = "src/common/iana_language_subtag_registry_list.cpp"
    entry_formatter = lambda do |entry|
      if entry[:prefix]
        prefix = 'VS{ ' + entry[:prefix].sort.map(&:to_cpp_string).join(', ') + ' }'
      else
        prefix = 'VS{}'
      end

      [ entry[:subtag].downcase.to_cpp_string,
        entry[:description].to_u8_cpp_string,
        prefix,
      ]
    end

    formatter = lambda do |type, name|
      rows = entries[type].map(&entry_formatter)

      "  g_#{name}.reserve(#{entries[type].size});\n\n" +
        format_table(rows.sort, :column_suffix => ',', :row_prefix => "  g_#{name}.emplace_back(", :row_suffix => ");").join("\n") +
        "\n"
    end

    formatted = [
      formatter.call("extlang", "extlangs"),
      formatter.call("variant", "variants"),
    ]

    header = <<EOT
/*
   mkvmerge -- utility for splicing together matroska files
   from component media subtypes

   Distributed under the GPL v2
   see the file COPYING for details
   or visit https://www.gnu.org/licenses/old-licenses/gpl-2.0.html

   IANA language subtag registry

   Written by Moritz Bunkus <moritz@bunkus.org>.
*/

// ----------------------------------------------------------------------------------------------
// NOTE: this file is auto-generated by the "dev:iana_language_subtag_registry_list" rake target.
// ----------------------------------------------------------------------------------------------

#include "common/common_pch.h"

#include "common/iana_language_subtag_registry.h"

namespace mtx::iana::language_subtag_registry {

std::vector<entry_t> g_extlangs, g_variants;

using VS = std::vector<std::string>;

void
init() {
EOT

    footer = <<EOT
}

} // namespace mtx::iana::language_subtag_registry
EOT

    content = header +
      formatted.join("\n") +
      footer

    runq("write", cpp_file_name) { IO.write("#{$source_dir}/#{cpp_file_name}", content); 0 }
  end

  def self.create_cpp
    do_create_cpp(self.fetch_registry)
  end
end
