#!/usr/bin/ruby

require 'set'
require 'optparse'

def generate_keys_file(opts)
  tables = []
  strings = {}
  lang_count = 0
  all_langs = []

  Dir.glob("**/*.lproj/*.strings").each do |filename|
    if filename.start_with?("Pods")
      next
    end

    if opts[:verbose]
      puts "Processing: #{ filename }"
    end

    table_basename = File.basename(filename, ".strings")
    if not tables.include? table_basename
      tables << table_basename
    end
    
    lang = filename[/[^\.]*/].split("/").last
    
    File.open(filename, "r:UTF-8") do |f|
      contents = f.read
      contents.scan(/^\"([^\"]*)\"\s=\s\"(.*)\";/) do |key, value|
      	key = key.split().join("_")

        strings[key] ||= {}
        strings[key][lang] = value
      end
    end
  end

  strings.each do |key, value|
    if (value.count > lang_count) then
      lang_count = value.count
      all_langs = value.keys
    end
  end

  f = File.open("#{ opts[:output] }/MKLocalizationKeys.h", "w")
  f.write("// Header automatically generated by MiawKit. Do not edit.\n")
  if opts[:includes_date]
    f.write("// Generated on #{ Time.now.asctime }\n")
  end
  f.write("\n")
  f.write("#import <Foundation/Foundation.h>\n");
  f.write("\n")
  f.write("#ifndef MK_LOCALIZATION_KEYS\n")
  f.write("#define MK_LOCALIZATION_KEYS\n")
  f.write("\n")

  tables.each do |table|
    f.write("/*!\n")
    f.write(" * #{ table } strings file \n")
    f.write(" */\n")
    f.write("static NSString * const #{ table } = @\"#{ table }\";\n\n")
  end

  strings.each do |key, value|
    if (value.count != lang_count) and opts[:warnings] then
      missing_langs = all_langs.inject([]) { |a, v| if not value.keys.include? v then a << v else a end }
      f.write("#warning Missing languages #{ missing_langs.join(', ') } for key '#{key}'\n");
    end

    f.write("/*!\n")
  
    value.each do |lang, desc|
      if (lang == opts[:default_language]) then
        f.write(" * \"#{ desc }\"\n\n")
      end
    end
  
    f.write(" * All translations:\n\n")
  
    value.each do |lang, desc|
      f.write(" * @b #{ lang }@: \"#{ desc }\"\n\n")
    end
  
    f.write(" */\n")
    f.write("static NSString * const #{key.gsub("%", "").gsub("@", "X").gsub(".", "_").gsub(/^[\d]/, 'n\0')} = @\"#{ key }\";\n\n")
  end

  f.write("                                               \n")
  f.write("#endif                                         \n")

  f.close()
end

options = { :output => ".",
            :default_language => "en",
            :verbose => false,
            :includes_date => true,
            :warnings => true }
gopts = nil
OptionParser.new do |opts|
  opts.banner = "Usage: #{ $PROGRAM_NAME } -g [options]"
  opts.on("-oPATH", "--output=PATH", String, "Specify output path.") do |o|
    if !File.directory?(o)
      puts "Specified output directory does not exist: #{ o }"
      exit
    end
    options[:output] = o
  end

  opts.on("-g", "--generate", "Generates a header with all localization keys.") do |g|
    options[:generate] = true
  end

  opts.on("-w", "--nowarn", "Skips warnings for missing strings.") do |g|
    options[:warnings] = false
  end

  opts.on("-l", "--language", "Code of your development language. Default is en.") do |l|
    options[:default_language] = l
  end

  opts.on("-d", "--no-date", "Removes the date from the header.") do |d|
    options[:includes_date] = d
  end

  opts.on("-v", "--verbose", "Set verbosity.") do |v|
    options[:verbose] = v
  end

  opts.on("-h", "--help", "Displays this information.") do
    puts opts
    exit
  end

  gopts = opts
end.parse!

if options.has_key?(:generate) then
  generate_keys_file(options)
else
  puts gopts
end