#!/usr/bin/python

# Copyright (c) 2009 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# Usage: generate_localizer [xib_path] [output_dot_h_path] [output_dot_mm_path]
#
# Extracts all the localizable strings that start with "^IDS" from the given
# xib file, and then generates a localizer to process those strings.

import os.path
import plistlib
import subprocess
import sys

generate_localizer = "me"

localizer_template_h = \
'''//          ---------- WARNING ----------
// THIS IS A GENERATED FILE, DO NOT EDIT IT DIRECTLY!
//
// Generated by %(generate_localizer)s.
// Generated from %(xib_file)s.
//

#ifndef %(class_name)s_LOCALIZER_H_
#define %(class_name)s_LOCALIZER_H_

#import "chrome/browser/cocoa/ui_localizer.h"

// A subclass of ChromeUILocalizer that handles localization based on resource
// constants.

@interface %(class_name)sLocalizer : ChromeUILocalizer
@end

#endif  // %(class_name)s_LOCALIZER_H_
'''

localizer_template_mm = \
'''//          ---------- WARNING ----------
// THIS IS A GENERATED FILE, DO NOT EDIT IT DIRECTLY!
//
// Generated by '%(generate_localizer)s'.
// Generated from '%(xib_file)s'.
//

#import "%(header_name)s"

#include "grit/app_strings.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"

@implementation %(class_name)sLocalizer

- (NSString *)localizedStringForString:(NSString *)string {

  static const ui_localizer::ResourceMap kUIResources[] = {
%(resource_map_list)s  };
  static const size_t kUIResourcesSize = arraysize(kUIResources);

  return ui_localizer::LocalizedStringForKeyFromMapList(string,
                                                        kUIResources,
                                                        kUIResourcesSize);
}

@end
'''

def xib_localizable_strings(xib_path):
  """Runs ibtool to extract the localizable strings data from the xib."""
  ibtool_cmd = subprocess.Popen(['/usr/bin/ibtool', '--localizable-strings',
                                 xib_path],
                                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  (cmd_out, cmd_err) = ibtool_cmd.communicate()
  if ibtool_cmd.returncode:
    sys.stderr.write('%s:0: error: ibtool on "%s" failed (%d):\n%s\n' %
                     (generate_localizer, xib_path, ibtool_cmd.returncode,
                      cmd_err))
    return None
  return cmd_out

def extract_resource_constants(plist_localizable_strings_dict, xib_path):
  """Extracts all the values that start with ^IDS from the localizable
  strings plist entry."""
  constants_list = []
  for item_dict in plist_localizable_strings_dict.itervalues():
    for item_value in item_dict.itervalues():
      if item_value.startswith('^IDS'):
        constants_list.append(item_value)
      elif item_value.startswith('IDS'):
        sys.stderr.write(
            '%s:0: warning: %s found a string with questionable prefix, "%s"\n'
            % (xib_path, generate_localizer, item_value));
  return constants_list

def generate_files_contents(class_name, constants_list, header_name, xib_path):
  """Generates a localizer files contents from the list of constants."""
  # Bounce through a set to uniq the strings, sort the list, then build the
  # values we need from it.
  constants_list = sorted(set(constants_list))
  constant_list_str = ''
  for item in constants_list:
    parts = item.split('$', 1)
    label_id = parts[0]
    if len(parts) == 2:
      label_arg_id = parts[1]
    else:
      label_arg_id = '0'
    constant_list_str += '    { "%s", %s, %s },\n' % \
        ( item, label_id[1:], label_arg_id)
  # Assemble the contents from the templates.
  values_dict = {
    'class_name': class_name,
    'header_name': header_name,
    'resource_map_list': constant_list_str,
    'generate_localizer': generate_localizer,
    'xib_file': xib_path,
  }
  h_file = localizer_template_h % values_dict
  mm_file = localizer_template_mm % values_dict
  return (h_file, mm_file)


def Main(argv=None):
  global generate_localizer
  generate_localizer = os.path.basename(argv[0])

  # Args
  if len(argv) != 4:
    sys.stderr.write('%s:0: error: Expected xib and output file arguments\n' %
                     generate_localizer);
    return 1
  xib_path, output_h_path, output_mm_path = argv[1:]

  # Run ibtool and convert to something Python can deal with
  plist_string = xib_localizable_strings(xib_path)
  if not plist_string:
    return 2
  plist = plistlib.readPlistFromString(plist_string)

  # Extract the resource constant strings
  localizable_strings = plist['com.apple.ibtool.document.localizable-strings']
  constants_list = extract_resource_constants(localizable_strings, xib_path)
  if not constants_list:
    sys.stderr.write("%s:0: warning: %s didn't find any resource strings\n" %
                     (xib_path, generate_localizer));
    # Seed constant_list with an entry so things will compile even though the
    # array sould really be empty (array_size in the generated file doesn't
    # like an empty array).
    constants_list.append('^0');

  # Name the class based on the output file
  class_name = os.path.splitext(os.path.basename(output_h_path))[0]
  suffix = '_localizer'
  if class_name.endswith(suffix):
    class_name = class_name[:-len(suffix)];
  class_name = class_name.replace('_', ' ').title().replace(' ', '');

  # Generate our file contents
  (h_file_content, mm_file_content) = \
      generate_files_contents(class_name, constants_list,
                              os.path.basename(output_h_path),
                              xib_path)

  # Write out the files
  file_fd = open(output_h_path, 'w')
  file_fd.write(h_file_content)
  file_fd.close()
  file_fd = open(output_mm_path, 'w')
  file_fd.write(mm_file_content)
  file_fd.close()

  return 0

if __name__ == '__main__':
  sys.exit(Main(sys.argv))