#!/usr/bin/env 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 argparse
import logging
import os
import plistlib
import subprocess
import sys

generate_localizer = "me"

localizer_template_h = \
'''//          ---------- WARNING ----------
// THIS IS A GENERATED FILE, DO NOT EDIT IT DIRECTLY!
//
// This header includes the table used by ui_localizer.mm.  Nothing else should
// be including this file.
//
// Generated by %(generate_localizer)s.
// Generated from:
//     %(xib_files)s
//

#ifndef CHROME_APP_NIBS_LOCALIZER_TABLE_H_
#define CHROME_APP_NIBS_LOCALIZER_TABLE_H_

static const UILocalizerResourceMap kUIResources[] = {
%(resource_map_list)s  };
static const size_t kUIResourcesSize = base::size(kUIResources);

#endif  // CHROME_APP_NIBS_LOCALIZER_TABLE_H_
'''

def xib_localizable_strings(xib_path, xcode_path):
  """Runs ibtool to extract the localizable strings data from the xib."""
  # Take SDKROOT out of the environment passed to ibtool. ibtool itself has
  # no need for it, but when ibtool runs via xcrun and Xcode isn't aware of
  # the SDK in use, its presence causes an error.
  ibtool_env = os.environ.copy()
  if 'SDKROOT' in os.environ:
    del ibtool_env['SDKROOT']
  if xcode_path:
    ibtool_env['DEVELOPER_DIR'] = xcode_path

  command = ['xcrun', 'ibtool', '--localizable-strings', xib_path]
  ibtool_cmd = subprocess.Popen(command,
                                stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                                env=ibtool_env)
  (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_file_contents(constants_list, xib_paths):
  """Generates the header listing the 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 = {
    'resource_map_list': constant_list_str,
    'generate_localizer': generate_localizer,
    'xib_files': "\n//     ".join(xib_paths),
  }
  h_file = localizer_template_h % values_dict
  return h_file


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

  parser = argparse.ArgumentParser(
      description='Generates a header file that localizes libs.')
  parser.add_argument('--output_path', required=True,
                      help='Path to output header file.')
  parser.add_argument('--developer_dir', required=False,
                      help='Path to Xcode.')
  parser.add_argument('xibs', nargs='+',
                      help='A list of xibs to localize')
  args = parser.parse_args()

  output_path = args.output_path
  xib_paths = args.xibs

  full_constants_list = []
  for xib_path in xib_paths:
    # Run ibtool and convert to something Python can deal with
    plist_string = xib_localizable_strings(xib_path, args.developer_dir)
    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));
    full_constants_list.extend(constants_list)

  # Generate our file contents
  h_file_content = \
      generate_file_contents(full_constants_list, xib_paths)

  # Write out the file
  file_fd = open(output_path, 'w')
  file_fd.write(h_file_content)
  file_fd.close()

  return 0

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