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

"""Xcode project file generator.

This module is both an Xcode project file generator and a documentation of the
Xcode project file format.  Knowledge of the project file format was gained
based on extensive experience with Xcode, and by making changes to projects in
Xcode.app and observing the resultant changes in the associated project files.

XCODE PROJECT FILES

The generator targets the file format as written by Xcode 3.2 (specifically,
3.2.6), but past experience has taught that the format has not changed
significantly in the past several years, and future versions of Xcode are able
to read older project files.

Xcode project files are "bundled": the project "file" from an end-user's
perspective is actually a directory with an ".xcodeproj" extension.  The
project file from this module's perspective is actually a file inside this
directory, always named "project.pbxproj".  This file contains a complete
description of the project and is all that is needed to use the xcodeproj.
Other files contained in the xcodeproj directory are simply used to store
per-user settings, such as the state of various UI elements in the Xcode
application.

The project.pbxproj file is a property list, stored in a format almost
identical to the NeXTstep property list format.  The file is able to carry
Unicode data, and is encoded in UTF-8.  The root element in the property list
is a dictionary that contains several properties of minimal interest, and two
properties of immense interest.  The most important property is a dictionary
named "objects".  The entire structure of the project is represented by the
children of this property.  The objects dictionary is keyed by unique 96-bit
values represented by 24 uppercase hexadecimal characters.  Each value in the
objects dictionary is itself a dictionary, describing an individual object.

Each object in the dictionary is a member of a class, which is identified by
the "isa" property of each object.  A variety of classes are represented in a
project file.  Objects can refer to other objects by ID, using the 24-character
hexadecimal object key.  A project's objects form a tree, with a root object
of class PBXProject at the root.  As an example, the PBXProject object serves
as parent to an XCConfigurationList object defining the build configurations
used in the project, a PBXGroup object serving as a container for all files
referenced in the project, and a list of target objects, each of which defines
a target in the project.  There are several different types of target object,
such as PBXNativeTarget and PBXAggregateTarget.  In this module, this
relationship is expressed by having each target type derive from an abstract
base named XCTarget.

The project.pbxproj file's root dictionary also contains a property, sibling to
the "objects" dictionary, named "rootObject".  The value of rootObject is a
24-character object key referring to the root PBXProject object in the
objects dictionary.

In Xcode, every file used as input to a target or produced as a final product
of a target must appear somewhere in the hierarchy rooted at the PBXGroup
object referenced by the PBXProject's mainGroup property.  A PBXGroup is
generally represented as a folder in the Xcode application.  PBXGroups can
contain other PBXGroups as well as PBXFileReferences, which are pointers to
actual files.

Each XCTarget contains a list of build phases, represented in this module by
the abstract base XCBuildPhase.  Examples of concrete XCBuildPhase derivations
are PBXSourcesBuildPhase and PBXFrameworksBuildPhase, which correspond to the
"Compile Sources" and "Link Binary With Libraries" phases displayed in the
Xcode application.  Files used as input to these phases (for example, source
files in the former case and libraries and frameworks in the latter) are
represented by PBXBuildFile objects, referenced by elements of "files" lists
in XCTarget objects.  Each PBXBuildFile object refers to a PBXBuildFile
object as a "weak" reference: it does not "own" the PBXBuildFile, which is
owned by the root object's mainGroup or a descendant group.  In most cases, the
layer of indirection between an XCBuildPhase and a PBXFileReference via a
PBXBuildFile appears extraneous, but there's actually one reason for this:
file-specific compiler flags are added to the PBXBuildFile object so as to
allow a single file to be a member of multiple targets while having distinct
compiler flags for each.  These flags can be modified in the Xcode applciation
in the "Build" tab of a File Info window.

When a project is open in the Xcode application, Xcode will rewrite it.  As
such, this module is careful to adhere to the formatting used by Xcode, to
avoid insignificant changes appearing in the file when it is used in the
Xcode application.  This will keep version control repositories happy, and
makes it possible to compare a project file used in Xcode to one generated by
this module to determine if any significant changes were made in the
application.

Xcode has its own way of assigning 24-character identifiers to each object,
which is not duplicated here.  Because the identifier only is only generated
once, when an object is created, and is then left unchanged, there is no need
to attempt to duplicate Xcode's behavior in this area.  The generator is free
to select any identifier, even at random, to refer to the objects it creates,
and Xcode will retain those identifiers and use them when subsequently
rewriting the project file.  However, the generator would choose new random
identifiers each time the project files are generated, leading to difficulties
comparing "used" project files to "pristine" ones produced by this module,
and causing the appearance of changes as every object identifier is changed
when updated projects are checked in to a version control repository.  To
mitigate this problem, this module chooses identifiers in a more deterministic
way, by hashing a description of each object as well as its parent and ancestor
objects.  This strategy should result in minimal "shift" in IDs as successive
generations of project files are produced.

THIS MODULE

This module introduces several classes, all derived from the XCObject class.
Nearly all of the "brains" are built into the XCObject class, which understands
how to create and modify objects, maintain the proper tree structure, compute
identifiers, and print objects.  For the most part, classes derived from
XCObject need only provide a _schema class object, a dictionary that
expresses what properties objects of the class may contain.

Given this structure, it's possible to build a minimal project file by creating
objects of the appropriate types and making the proper connections:

  config_list = XCConfigurationList()
  group = PBXGroup()
  project = PBXProject({'buildConfigurationList': config_list,
                        'mainGroup': group})

With the project object set up, it can be added to an XCProjectFile object.
XCProjectFile is a pseudo-class in the sense that it is a concrete XCObject
subclass that does not actually correspond to a class type found in a project
file.  Rather, it is used to represent the project file's root dictionary.
Printing an XCProjectFile will print the entire project file, including the
full "objects" dictionary.

  project_file = XCProjectFile({'rootObject': project})
  project_file.ComputeIDs()
  project_file.Print()

Xcode project files are always encoded in UTF-8.  This module will accept
strings of either the str class or the unicode class.  Strings of class str
are assumed to already be encoded in UTF-8.  Obviously, if you're just using
ASCII, you won't encounter difficulties because ASCII is a UTF-8 subset.
Strings of class unicode are handled properly and encoded in UTF-8 when
a project file is output.
"""

import gyp.common
import posixpath
import re
import struct
import sys

# hashlib is supplied as of Python 2.5 as the replacement interface for sha
# and other secure hashes.  In 2.6, sha is deprecated.  Import hashlib if
# available, avoiding a deprecation warning under 2.6.  Import sha otherwise,
# preserving 2.4 compatibility.
try:
  import hashlib
  _new_sha1 = hashlib.sha1
except ImportError:
  import sha
  _new_sha1 = sha.new


# See XCObject._EncodeString.  This pattern is used to determine when a string
# can be printed unquoted.  Strings that match this pattern may be printed
# unquoted.  Strings that do not match must be quoted and may be further
# transformed to be properly encoded.  Note that this expression matches the
# characters listed with "+", for 1 or more occurrences: if a string is empty,
# it must not match this pattern, because it needs to be encoded as "".
_unquoted = re.compile('^[A-Za-z0-9$./_]+$')

# Strings that match this pattern are quoted regardless of what _unquoted says.
# Oddly, Xcode will quote any string with a run of three or more underscores.
_quoted = re.compile('___')

# This pattern should match any character that needs to be escaped by
# XCObject._EncodeString.  See that function.
_escaped = re.compile('[\\\\"]|[\x00-\x1f]')


# Used by SourceTreeAndPathFromPath
_path_leading_variable = re.compile('^\$\((.*?)\)(/(.*))?$')

def SourceTreeAndPathFromPath(input_path):
  """Given input_path, returns a tuple with sourceTree and path values.

  Examples:
    input_path     (source_tree, output_path)
    '$(VAR)/path'  ('VAR', 'path')
    '$(VAR)'       ('VAR', None)
    'path'         (None, 'path')
  """

  source_group_match = _path_leading_variable.match(input_path)
  if source_group_match:
    source_tree = source_group_match.group(1)
    output_path = source_group_match.group(3)  # This may be None.
  else:
    source_tree = None
    output_path = input_path

  return (source_tree, output_path)

def ConvertVariablesToShellSyntax(input_string):
  return re.sub('\$\((.*?)\)', '${\\1}', input_string)

class XCObject(object):
  """The abstract base of all class types used in Xcode project files.

  Class variables:
    _schema: A dictionary defining the properties of this class.  The keys to
             _schema are string property keys as used in project files.  Values
             are a list of four or five elements:
             [ is_list, property_type, is_strong, is_required, default ]
             is_list: True if the property described is a list, as opposed
                      to a single element.
             property_type: The type to use as the value of the property,
                            or if is_list is True, the type to use for each
                            element of the value's list.  property_type must
                            be an XCObject subclass, or one of the built-in
                            types str, int, or dict.
             is_strong: If property_type is an XCObject subclass, is_strong
                        is True to assert that this class "owns," or serves
                        as parent, to the property value (or, if is_list is
                        True, values).  is_strong must be False if
                        property_type is not an XCObject subclass.
             is_required: True if the property is required for the class.
                          Note that is_required being True does not preclude
                          an empty string ("", in the case of property_type
                          str) or list ([], in the case of is_list True) from
                          being set for the property.
             default: Optional.  If is_requried is True, default may be set
                      to provide a default value for objects that do not supply
                      their own value.  If is_required is True and default
                      is not provided, users of the class must supply their own
                      value for the property.
             Note that although the values of the array are expressed in
             boolean terms, subclasses provide values as integers to conserve
             horizontal space.
    _should_print_single_line: False in XCObject.  Subclasses whose objects
                               should be written to the project file in the
                               alternate single-line format, such as
                               PBXFileReference and PBXBuildFile, should
                               set this to True.
    _encode_transforms: Used by _EncodeString to encode unprintable characters.
                        The index into this list is the ordinal of the
                        character to transform; each value is a string
                        used to represent the character in the output.  XCObject
                        provides an _encode_transforms list suitable for most
                        XCObject subclasses.
    _alternate_encode_transforms: Provided for subclasses that wish to use
                                  the alternate encoding rules.  Xcode seems
                                  to use these rules when printing objects in
                                  single-line format.  Subclasses that desire
                                  this behavior should set _encode_transforms
                                  to _alternate_encode_transforms.
    _hashables: A list of XCObject subclasses that can be hashed by ComputeIDs
                to construct this object's ID.  Most classes that need custom
                hashing behavior should do it by overriding Hashables,
                but in some cases an object's parent may wish to push a
                hashable value into its child, and it can do so by appending
                to _hashables.
  Attributes:
    id: The object's identifier, a 24-character uppercase hexadecimal string.
        Usually, objects being created should not set id until the entire
        project file structure is built.  At that point, UpdateIDs() should
        be called on the root object to assign deterministic values for id to
        each object in the tree.
    parent: The object's parent.  This is set by a parent XCObject when a child
            object is added to it.
    _properties: The object's property dictionary.  An object's properties are
                 described by its class' _schema variable.
  """

  _schema = {}
  _should_print_single_line = False

  # See _EncodeString.
  _encode_transforms = []
  i = 0
  while i < ord(' '):
    _encode_transforms.append('\\U%04x' % i)
    i = i + 1
  _encode_transforms[7] = '\\a'
  _encode_transforms[8] = '\\b'
  _encode_transforms[9] = '\\t'
  _encode_transforms[10] = '\\n'
  _encode_transforms[11] = '\\v'
  _encode_transforms[12] = '\\f'
  _encode_transforms[13] = '\\n'

  _alternate_encode_transforms = list(_encode_transforms)
  _alternate_encode_transforms[9] = chr(9)
  _alternate_encode_transforms[10] = chr(10)
  _alternate_encode_transforms[11] = chr(11)

  def __init__(self, properties=None, id=None, parent=None):
    self.id = id
    self.parent = parent
    self._properties = {}
    self._hashables = []
    self._SetDefaultsFromSchema()
    self.UpdateProperties(properties)

  def __repr__(self):
    try:
      name = self.Name()
    except NotImplementedError:
      return '<%s at 0x%x>' % (self.__class__.__name__, id(self))
    return '<%s %r at 0x%x>' % (self.__class__.__name__, name, id(self))

  def Copy(self):
    """Make a copy of this object.

    The new object will have its own copy of lists and dicts.  Any XCObject
    objects owned by this object (marked "strong") will be copied in the
    new object, even those found in lists.  If this object has any weak
    references to other XCObjects, the same references are added to the new
    object without making a copy.
    """

    that = self.__class__(id=self.id, parent=self.parent)
    for key, value in self._properties.iteritems():
      is_strong = self._schema[key][2]

      if isinstance(value, XCObject):
        if is_strong:
          new_value = value.Copy()
          new_value.parent = that
          that._properties[key] = new_value
        else:
          that._properties[key] = value
      elif isinstance(value, str) or isinstance(value, unicode) or \
           isinstance(value, int):
        that._properties[key] = value
      elif isinstance(value, list):
        if is_strong:
          # If is_strong is True, each element is an XCObject, so it's safe to
          # call Copy.
          that._properties[key] = []
          for item in value:
            new_item = item.Copy()
            new_item.parent = that
            that._properties[key].append(new_item)
        else:
          that._properties[key] = value[:]
      elif isinstance(value, dict):
        # dicts are never strong.
        if is_strong:
          raise TypeError, 'Strong dict for key ' + key + ' in ' + \
                           self.__class__.__name__
        else:
          that._properties[key] = value.copy()
      else:
        raise TypeError, 'Unexpected type ' + value.__class__.__name__ + \
                         ' for key ' + key + ' in ' + self.__class__.__name__

    return that

  def Name(self):
    """Return the name corresponding to an object.

    Not all objects necessarily need to be nameable, and not all that do have
    a "name" property.  Override as needed.
    """

    # If the schema indicates that "name" is required, try to access the
    # property even if it doesn't exist.  This will result in a KeyError
    # being raised for the property that should be present, which seems more
    # appropriate than NotImplementedError in this case.
    if 'name' in self._properties or \
        ('name' in self._schema and self._schema['name'][3]):
      return self._properties['name']

    raise NotImplementedError, \
          self.__class__.__name__ + ' must implement Name'

  def Comment(self):
    """Return a comment string for the object.

    Most objects just use their name as the comment, but PBXProject uses
    different values.

    The returned comment is not escaped and does not have any comment marker
    strings applied to it.
    """

    return self.Name()

  def Hashables(self):
    hashables = [self.__class__.__name__]

    name = self.Name()
    if name != None:
      hashables.append(name)

    hashables.extend(self._hashables)

    return hashables

  def HashablesForChild(self):
    return None

  def ComputeIDs(self, recursive=True, overwrite=True, seed_hash=None):
    """Set "id" properties deterministically.

    An object's "id" property is set based on a hash of its class type and
    name, as well as the class type and name of all ancestor objects.  As
    such, it is only advisable to call ComputeIDs once an entire project file
    tree is built.

    If recursive is True, recurse into all descendant objects and update their
    hashes.

    If overwrite is True, any existing value set in the "id" property will be
    replaced.
    """

    def _HashUpdate(hash, data):
      """Update hash with data's length and contents.

      If the hash were updated only with the value of data, it would be
      possible for clowns to induce collisions by manipulating the names of
      their objects.  By adding the length, it's exceedingly less likely that
      ID collisions will be encountered, intentionally or not.
      """

      hash.update(struct.pack('>i', len(data)))
      hash.update(data)

    if seed_hash is None:
      seed_hash = _new_sha1()

    hash = seed_hash.copy()

    hashables = self.Hashables()
    assert len(hashables) > 0
    for hashable in hashables:
      _HashUpdate(hash, hashable)

    if recursive:
      hashables_for_child = self.HashablesForChild()
      if hashables_for_child is None:
        child_hash = hash
      else:
        assert len(hashables_for_child) > 0
        child_hash = seed_hash.copy()
        for hashable in hashables_for_child:
          _HashUpdate(child_hash, hashable)

      for child in self.Children():
        child.ComputeIDs(recursive, overwrite, child_hash)

    if overwrite or self.id is None:
      # Xcode IDs are only 96 bits (24 hex characters), but a SHA-1 digest is
      # is 160 bits.  Instead of throwing out 64 bits of the digest, xor them
      # into the portion that gets used.
      assert hash.digest_size % 4 == 0
      digest_int_count = hash.digest_size / 4
      digest_ints = struct.unpack('>' + 'I' * digest_int_count, hash.digest())
      id_ints = [0, 0, 0]
      for index in xrange(0, digest_int_count):
        id_ints[index % 3] ^= digest_ints[index]
      self.id = '%08X%08X%08X' % tuple(id_ints)

  def EnsureNoIDCollisions(self):
    """Verifies that no two objects have the same ID.  Checks all descendants.
    """

    ids = {}
    descendants = self.Descendants()
    for descendant in descendants:
      if descendant.id in ids:
        other = ids[descendant.id]
        raise KeyError, \
              'Duplicate ID %s, objects "%s" and "%s" in "%s"' % \
              (descendant.id, str(descendant._properties),
               str(other._properties), self._properties['rootObject'].Name())
      ids[descendant.id] = descendant

  def Children(self):
    """Returns a list of all of this object's owned (strong) children."""

    children = []
    for property, attributes in self._schema.iteritems():
      (is_list, property_type, is_strong) = attributes[0:3]
      if is_strong and property in self._properties:
        if not is_list:
          children.append(self._properties[property])
        else:
          children.extend(self._properties[property])
    return children

  def Descendants(self):
    """Returns a list of all of this object's descendants, including this
    object.
    """

    children = self.Children()
    descendants = [self]
    for child in children:
      descendants.extend(child.Descendants())
    return descendants

  def PBXProjectAncestor(self):
    # The base case for recursion is defined at PBXProject.PBXProjectAncestor.
    if self.parent:
      return self.parent.PBXProjectAncestor()
    return None

  def _EncodeComment(self, comment):
    """Encodes a comment to be placed in the project file output, mimicing
    Xcode behavior.
    """

    # This mimics Xcode behavior by wrapping the comment in "/*" and "*/".  If
    # the string already contains a "*/", it is turned into "(*)/".  This keeps
    # the file writer from outputting something that would be treated as the
    # end of a comment in the middle of something intended to be entirely a
    # comment.

    return '/* ' + comment.replace('*/', '(*)/') + ' */'

  def _EncodeTransform(self, match):
    # This function works closely with _EncodeString.  It will only be called
    # by re.sub with match.group(0) containing a character matched by the
    # the _escaped expression.
    char = match.group(0)

    # Backslashes (\) and quotation marks (") are always replaced with a
    # backslash-escaped version of the same.  Everything else gets its
    # replacement from the class' _encode_transforms array.
    if char == '\\':
      return '\\\\'
    if char == '"':
      return '\\"'
    return self._encode_transforms[ord(char)]

  def _EncodeString(self, value):
    """Encodes a string to be placed in the project file output, mimicing
    Xcode behavior.
    """

    # Use quotation marks when any character outside of the range A-Z, a-z, 0-9,
    # $ (dollar sign), . (period), and _ (underscore) is present.  Also use
    # quotation marks to represent empty strings.
    #
    # Escape " (double-quote) and \ (backslash) by preceding them with a
    # backslash.
    #
    # Some characters below the printable ASCII range are encoded specially:
    #     7 ^G BEL is encoded as "\a"
    #     8 ^H BS  is encoded as "\b"
    #    11 ^K VT  is encoded as "\v"
    #    12 ^L NP  is encoded as "\f"
    #   127 ^? DEL is passed through as-is without escaping
    #  - In PBXFileReference and PBXBuildFile objects:
    #     9 ^I HT  is passed through as-is without escaping
    #    10 ^J NL  is passed through as-is without escaping
    #    13 ^M CR  is passed through as-is without escaping
    #  - In other objects:
    #     9 ^I HT  is encoded as "\t"
    #    10 ^J NL  is encoded as "\n"
    #    13 ^M CR  is encoded as "\n" rendering it indistinguishable from
    #              10 ^J NL
    # All other characters within the ASCII control character range (0 through
    # 31 inclusive) are encoded as "\U001f" referring to the Unicode code point
    # in hexadecimal.  For example, character 14 (^N SO) is encoded as "\U000e".
    # Characters above the ASCII range are passed through to the output encoded
    # as UTF-8 without any escaping.  These mappings are contained in the
    # class' _encode_transforms list.

    if _unquoted.search(value) and not _quoted.search(value):
      return value

    return '"' + _escaped.sub(self._EncodeTransform, value) + '"'

  def _XCPrint(self, file, tabs, line):
    file.write('\t' * tabs + line)

  def _XCPrintableValue(self, tabs, value, flatten_list=False):
    """Returns a representation of value that may be printed in a project file,
    mimicing Xcode's behavior.

    _XCPrintableValue can handle str and int values, XCObjects (which are
    made printable by returning their id property), and list and dict objects
    composed of any of the above types.  When printing a list or dict, and
    _should_print_single_line is False, the tabs parameter is used to determine
    how much to indent the lines corresponding to the items in the list or
    dict.

    If flatten_list is True, single-element lists will be transformed into
    strings.
    """

    printable = ''
    comment = None

    if self._should_print_single_line:
      sep = ' '
      element_tabs = ''
      end_tabs = ''
    else:
      sep = '\n'
      element_tabs = '\t' * (tabs + 1)
      end_tabs = '\t' * tabs

    if isinstance(value, XCObject):
      printable += value.id
      comment = value.Comment()
    elif isinstance(value, str):
      printable += self._EncodeString(value)
    elif isinstance(value, unicode):
      printable += self._EncodeString(value.encode('utf-8'))
    elif isinstance(value, int):
      printable += str(value)
    elif isinstance(value, list):
      if flatten_list and len(value) <= 1:
        if len(value) == 0:
          printable += self._EncodeString('')
        else:
          printable += self._EncodeString(value[0])
      else:
        printable = '(' + sep
        for item in value:
          printable += element_tabs + \
                       self._XCPrintableValue(tabs + 1, item, flatten_list) + \
                       ',' + sep
        printable += end_tabs + ')'
    elif isinstance(value, dict):
      printable = '{' + sep
      for item_key, item_value in sorted(value.iteritems()):
        printable += element_tabs + \
            self._XCPrintableValue(tabs + 1, item_key, flatten_list) + ' = ' + \
            self._XCPrintableValue(tabs + 1, item_value, flatten_list) + ';' + \
            sep
      printable += end_tabs + '}'
    else:
      raise TypeError, "Can't make " + value.__class__.__name__ + ' printable'

    if comment != None:
      printable += ' ' + self._EncodeComment(comment)

    return printable

  def _XCKVPrint(self, file, tabs, key, value):
    """Prints a key and value, members of an XCObject's _properties dictionary,
    to file.

    tabs is an int identifying the indentation level.  If the class'
    _should_print_single_line variable is True, tabs is ignored and the
    key-value pair will be followed by a space insead of a newline.
    """

    if self._should_print_single_line:
      printable = ''
      after_kv = ' '
    else:
      printable = '\t' * tabs
      after_kv = '\n'

    # Xcode usually prints remoteGlobalIDString values in PBXContainerItemProxy
    # objects without comments.  Sometimes it prints them with comments, but
    # the majority of the time, it doesn't.  To avoid unnecessary changes to
    # the project file after Xcode opens it, don't write comments for
    # remoteGlobalIDString.  This is a sucky hack and it would certainly be
    # cleaner to extend the schema to indicate whether or not a comment should
    # be printed, but since this is the only case where the problem occurs and
    # Xcode itself can't seem to make up its mind, the hack will suffice.
    #
    # Also see PBXContainerItemProxy._schema['remoteGlobalIDString'].
    if key == 'remoteGlobalIDString' and isinstance(self,
                                                    PBXContainerItemProxy):
      value_to_print = value.id
    else:
      value_to_print = value

    # PBXBuildFile's settings property is represented in the output as a dict,
    # but a hack here has it represented as a string. Arrange to strip off the
    # quotes so that it shows up in the output as expected.
    if key == 'settings' and isinstance(self, PBXBuildFile):
      strip_value_quotes = True
    else:
      strip_value_quotes = False

    # In another one-off, let's set flatten_list on buildSettings properties
    # of XCBuildConfiguration objects, because that's how Xcode treats them.
    if key == 'buildSettings' and isinstance(self, XCBuildConfiguration):
      flatten_list = True
    else:
      flatten_list = False

    try:
      printable_key = self._XCPrintableValue(tabs, key, flatten_list)
      printable_value = self._XCPrintableValue(tabs, value_to_print,
                                               flatten_list)
      if strip_value_quotes and len(printable_value) > 1 and \
          printable_value[0] == '"' and printable_value[-1] == '"':
        printable_value = printable_value[1:-1]
      printable += printable_key + ' = ' + printable_value + ';' + after_kv
    except TypeError, e:
      gyp.common.ExceptionAppend(e,
                                 'while printing key "%s"' % key)
      raise

    self._XCPrint(file, 0, printable)

  def Print(self, file=sys.stdout):
    """Prints a reprentation of this object to file, adhering to Xcode output
    formatting.
    """

    self.VerifyHasRequiredProperties()

    if self._should_print_single_line:
      # When printing an object in a single line, Xcode doesn't put any space
      # between the beginning of a dictionary (or presumably a list) and the
      # first contained item, so you wind up with snippets like
      #   ...CDEF = {isa = PBXFileReference; fileRef = 0123...
      # If it were me, I would have put a space in there after the opening
      # curly, but I guess this is just another one of those inconsistencies
      # between how Xcode prints PBXFileReference and PBXBuildFile objects as
      # compared to other objects.  Mimic Xcode's behavior here by using an
      # empty string for sep.
      sep = ''
      end_tabs = 0
    else:
      sep = '\n'
      end_tabs = 2

    # Start the object.  For example, '\t\tPBXProject = {\n'.
    self._XCPrint(file, 2, self._XCPrintableValue(2, self) + ' = {' + sep)

    # "isa" isn't in the _properties dictionary, it's an intrinsic property
    # of the class which the object belongs to.  Xcode always outputs "isa"
    # as the first element of an object dictionary.
    self._XCKVPrint(file, 3, 'isa', self.__class__.__name__)

    # The remaining elements of an object dictionary are sorted alphabetically.
    for property, value in sorted(self._properties.iteritems()):
      self._XCKVPrint(file, 3, property, value)

    # End the object.
    self._XCPrint(file, end_tabs, '};\n')

  def UpdateProperties(self, properties, do_copy=False):
    """Merge the supplied properties into the _properties dictionary.

    The input properties must adhere to the class schema or a KeyError or
    TypeError exception will be raised.  If adding an object of an XCObject
    subclass and the schema indicates a strong relationship, the object's
    parent will be set to this object.

    If do_copy is True, then lists, dicts, strong-owned XCObjects, and
    strong-owned XCObjects in lists will be copied instead of having their
    references added.
    """

    if properties is None:
      return

    for property, value in properties.iteritems():
      # Make sure the property is in the schema.
      if not property in self._schema:
        raise KeyError, property + ' not in ' + self.__class__.__name__

      # Make sure the property conforms to the schema.
      (is_list, property_type, is_strong) = self._schema[property][0:3]
      if is_list:
        if value.__class__ != list:
          raise TypeError, \
                property + ' of ' + self.__class__.__name__ + \
                ' must be list, not ' + value.__class__.__name__
        for item in value:
          if not isinstance(item, property_type) and \
             not (item.__class__ == unicode and property_type == str):
            # Accept unicode where str is specified.  str is treated as
            # UTF-8-encoded.
            raise TypeError, \
                  'item of ' + property + ' of ' + self.__class__.__name__ + \
                  ' must be ' + property_type.__name__ + ', not ' + \
                  item.__class__.__name__
      elif not isinstance(value, property_type) and \
           not (value.__class__ == unicode and property_type == str):
        # Accept unicode where str is specified.  str is treated as
        # UTF-8-encoded.
        raise TypeError, \
              property + ' of ' + self.__class__.__name__ + ' must be ' + \
              property_type.__name__ + ', not ' + value.__class__.__name__

      # Checks passed, perform the assignment.
      if do_copy:
        if isinstance(value, XCObject):
          if is_strong:
            self._properties[property] = value.Copy()
          else:
            self._properties[property] = value
        elif isinstance(value, str) or isinstance(value, unicode) or \
             isinstance(value, int):
          self._properties[property] = value
        elif isinstance(value, list):
          if is_strong:
            # If is_strong is True, each element is an XCObject, so it's safe
            # to call Copy.
            self._properties[property] = []
            for item in value:
              self._properties[property].append(item.Copy())
          else:
            self._properties[property] = value[:]
        elif isinstance(value, dict):
          self._properties[property] = value.copy()
        else:
          raise TypeError, "Don't know how to copy a " + \
                           value.__class__.__name__ + ' object for ' + \
                           property + ' in ' + self.__class__.__name__
      else:
        self._properties[property] = value

      # Set up the child's back-reference to this object.  Don't use |value|
      # any more because it may not be right if do_copy is true.
      if is_strong:
        if not is_list:
          self._properties[property].parent = self
        else:
          for item in self._properties[property]:
            item.parent = self

  def HasProperty(self, key):
    return key in self._properties

  def GetProperty(self, key):
    return self._properties[key]

  def SetProperty(self, key, value):
    self.UpdateProperties({key: value})

  def DelProperty(self, key):
    if key in self._properties:
      del self._properties[key]

  def AppendProperty(self, key, value):
    # TODO(mark): Support ExtendProperty too (and make this call that)?

    # Schema validation.
    if not key in self._schema:
      raise KeyError, key + ' not in ' + self.__class__.__name__

    (is_list, property_type, is_strong) = self._schema[key][0:3]
    if not is_list:
      raise TypeError, key + ' of ' + self.__class__.__name__ + ' must be list'
    if not isinstance(value, property_type):
      raise TypeError, 'item of ' + key + ' of ' + self.__class__.__name__ + \
                       ' must be ' + property_type.__name__ + ', not ' + \
                       value.__class__.__name__

    # If the property doesn't exist yet, create a new empty list to receive the
    # item.
    if not key in self._properties:
      self._properties[key] = []

    # Set up the ownership link.
    if is_strong:
      value.parent = self

    # Store the item.
    self._properties[key].append(value)

  def VerifyHasRequiredProperties(self):
    """Ensure that all properties identified as required by the schema are
    set.
    """

    # TODO(mark): A stronger verification mechanism is needed.  Some
    # subclasses need to perform validation beyond what the schema can enforce.
    for property, attributes in self._schema.iteritems():
      (is_list, property_type, is_strong, is_required) = attributes[0:4]
      if is_required and not property in self._properties:
        raise KeyError, self.__class__.__name__ + ' requires ' + property

  def _SetDefaultsFromSchema(self):
    """Assign object default values according to the schema.  This will not
    overwrite properties that have already been set."""

    defaults = {}
    for property, attributes in self._schema.iteritems():
      (is_list, property_type, is_strong, is_required) = attributes[0:4]
      if is_required and len(attributes) >= 5 and \
          not property in self._properties:
        default = attributes[4]

        defaults[property] = default

    if len(defaults) > 0:
      # Use do_copy=True so that each new object gets its own copy of strong
      # objects, lists, and dicts.
      self.UpdateProperties(defaults, do_copy=True)


class XCHierarchicalElement(XCObject):
  """Abstract base for PBXGroup and PBXFileReference.  Not represented in a
  project file."""

  # TODO(mark): Do name and path belong here?  Probably so.
  # If path is set and name is not, name may have a default value.  Name will
  # be set to the basename of path, if the basename of path is different from
  # the full value of path.  If path is already just a leaf name, name will
  # not be set.
  _schema = XCObject._schema.copy()
  _schema.update({
    'comments':       [0, str, 0, 0],
    'fileEncoding':   [0, str, 0, 0],
    'includeInIndex': [0, int, 0, 0],
    'indentWidth':    [0, int, 0, 0],
    'lineEnding':     [0, int, 0, 0],
    'sourceTree':     [0, str, 0, 1, '<group>'],
    'tabWidth':       [0, int, 0, 0],
    'usesTabs':       [0, int, 0, 0],
    'wrapsLines':     [0, int, 0, 0],
  })

  def __init__(self, properties=None, id=None, parent=None):
    # super
    XCObject.__init__(self, properties, id, parent)
    if 'path' in self._properties and not 'name' in self._properties:
      path = self._properties['path']
      name = posixpath.basename(path)
      if name != '' and path != name:
        self.SetProperty('name', name)

    if 'path' in self._properties and \
        (not 'sourceTree' in self._properties or \
         self._properties['sourceTree'] == '<group>'):
      # If the pathname begins with an Xcode variable like "$(SDKROOT)/", take
      # the variable out and make the path be relative to that variable by
      # assigning the variable name as the sourceTree.
      (source_tree, path) = SourceTreeAndPathFromPath(self._properties['path'])
      if source_tree != None:
        self._properties['sourceTree'] = source_tree
      if path != None:
        self._properties['path'] = path
      if source_tree != None and path is None and \
         not 'name' in self._properties:
        # The path was of the form "$(SDKROOT)" with no path following it.
        # This object is now relative to that variable, so it has no path
        # attribute of its own.  It does, however, keep a name.
        del self._properties['path']
        self._properties['name'] = source_tree

  def Name(self):
    if 'name' in self._properties:
      return self._properties['name']
    elif 'path' in self._properties:
      return self._properties['path']
    else:
      # This happens in the case of the root PBXGroup.
      return None

  def Hashables(self):
    """Custom hashables for XCHierarchicalElements.

    XCHierarchicalElements are special.  Generally, their hashes shouldn't
    change if the paths don't change.  The normal XCObject implementation of
    Hashables adds a hashable for each object, which means that if
    the hierarchical structure changes (possibly due to changes caused when
    TakeOverOnlyChild runs and encounters slight changes in the hierarchy),
    the hashes will change.  For example, if a project file initially contains
    a/b/f1 and a/b becomes collapsed into a/b, f1 will have a single parent
    a/b.  If someone later adds a/f2 to the project file, a/b can no longer be
    collapsed, and f1 winds up with parent b and grandparent a.  That would
    be sufficient to change f1's hash.

    To counteract this problem, hashables for all XCHierarchicalElements except
    for the main group (which has neither a name nor a path) are taken to be
    just the set of path components.  Because hashables are inherited from
    parents, this provides assurance that a/b/f1 has the same set of hashables
    whether its parent is b or a/b.

    The main group is a special case.  As it is permitted to have no name or
    path, it is permitted to use the standard XCObject hash mechanism.  This
    is not considered a problem because there can be only one main group.
    """

    if self == self.PBXProjectAncestor()._properties['mainGroup']:
      # super
      return XCObject.Hashables(self)

    hashables = []

    # Put the name in first, ensuring that if TakeOverOnlyChild collapses
    # children into a top-level group like "Source", the name always goes
    # into the list of hashables without interfering with path components.
    if 'name' in self._properties:
      # Make it less likely for people to manipulate hashes by following the
      # pattern of always pushing an object type value onto the list first.
      hashables.append(self.__class__.__name__ + '.name')
      hashables.append(self._properties['name'])

    # NOTE: This still has the problem that if an absolute path is encountered,
    # including paths with a sourceTree, they'll still inherit their parents'
    # hashables, even though the paths aren't relative to their parents.  This
    # is not expected to be much of a problem in practice.
    path = self.PathFromSourceTreeAndPath()
    if path != None:
      components = path.split(posixpath.sep)
      for component in components:
        hashables.append(self.__class__.__name__ + '.path')
        hashables.append(component)

    hashables.extend(self._hashables)

    return hashables

  def Compare(self, other):
    # Allow comparison of these types.  PBXGroup has the highest sort rank;
    # PBXVariantGroup is treated as equal to PBXFileReference.
    valid_class_types = {
      PBXFileReference: 'file',
      PBXGroup:         'group',
      PBXVariantGroup:  'file',
    }
    self_type = valid_class_types[self.__class__]
    other_type = valid_class_types[other.__class__]

    if self_type == other_type:
      # If the two objects are of the same sort rank, compare their names.
      return cmp(self.Name(), other.Name())

    # Otherwise, sort groups before everything else.
    if self_type == 'group':
      return -1
    return 1

  def CompareRootGroup(self, other):
    # This function should be used only to compare direct children of the
    # containing PBXProject's mainGroup.  These groups should appear in the
    # listed order.
    # TODO(mark): "Build" is used by gyp.generator.xcode, perhaps the
    # generator should have a way of influencing this list rather than having
    # to hardcode for the generator here.
    order = ['Source', 'Intermediates', 'Projects', 'Frameworks', 'Products',
             'Build']

    # If the groups aren't in the listed order, do a name comparison.
    # Otherwise, groups in the listed order should come before those that
    # aren't.
    self_name = self.Name()
    other_name = other.Name()
    self_in = isinstance(self, PBXGroup) and self_name in order
    other_in = isinstance(self, PBXGroup) and other_name in order
    if not self_in and not other_in:
      return self.Compare(other)
    if self_name in order and not other_name in order:
      return -1
    if other_name in order and not self_name in order:
      return 1

    # If both groups are in the listed order, go by the defined order.
    self_index = order.index(self_name)
    other_index = order.index(other_name)
    if self_index < other_index:
      return -1
    if self_index > other_index:
      return 1
    return 0

  def PathFromSourceTreeAndPath(self):
    # Turn the object's sourceTree and path properties into a single flat
    # string of a form comparable to the path parameter.  If there's a
    # sourceTree property other than "<group>", wrap it in $(...) for the
    # comparison.
    components = []
    if self._properties['sourceTree'] != '<group>':
      components.append('$(' + self._properties['sourceTree'] + ')')
    if 'path' in self._properties:
      components.append(self._properties['path'])

    if len(components) > 0:
      return posixpath.join(*components)

    return None

  def FullPath(self):
    # Returns a full path to self relative to the project file, or relative
    # to some other source tree.  Start with self, and walk up the chain of
    # parents prepending their paths, if any, until no more parents are
    # available (project-relative path) or until a path relative to some
    # source tree is found.
    xche = self
    path = None
    while isinstance(xche, XCHierarchicalElement) and \
          (path is None or \
           (not path.startswith('/') and not path.startswith('$'))):
      this_path = xche.PathFromSourceTreeAndPath()
      if this_path != None and path != None:
        path = posixpath.join(this_path, path)
      elif this_path != None:
        path = this_path
      xche = xche.parent

    return path


class PBXGroup(XCHierarchicalElement):
  """
  Attributes:
    _children_by_path: Maps pathnames of children of this PBXGroup to the
      actual child XCHierarchicalElement objects.
    _variant_children_by_name_and_path: Maps (name, path) tuples of
      PBXVariantGroup children to the actual child PBXVariantGroup objects.
  """

  _schema = XCHierarchicalElement._schema.copy()
  _schema.update({
    'children': [1, XCHierarchicalElement, 1, 1, []],
    'name':     [0, str,                   0, 0],
    'path':     [0, str,                   0, 0],
  })

  def __init__(self, properties=None, id=None, parent=None):
    # super
    XCHierarchicalElement.__init__(self, properties, id, parent)
    self._children_by_path = {}
    self._variant_children_by_name_and_path = {}
    for child in self._properties.get('children', []):
      self._AddChildToDicts(child)

  def Hashables(self):
    # super
    hashables = XCHierarchicalElement.Hashables(self)

    # It is not sufficient to just rely on name and parent to build a unique
    # hashable : a node could have two child PBXGroup sharing a common name.
    # To add entropy the hashable is enhanced with the names of all its
    # children.
    for child in self._properties.get('children', []):
      child_name = child.Name()
      if child_name != None:
        hashables.append(child_name)

    return hashables

  def HashablesForChild(self):
    # To avoid a circular reference the hashables used to compute a child id do
    # not include the child names.
    return XCHierarchicalElement.Hashables(self)

  def _AddChildToDicts(self, child):
    # Sets up this PBXGroup object's dicts to reference the child properly.
    child_path = child.PathFromSourceTreeAndPath()
    if child_path:
      if child_path in self._children_by_path:
        raise ValueError, 'Found multiple children with path ' + child_path
      self._children_by_path[child_path] = child

    if isinstance(child, PBXVariantGroup):
      child_name = child._properties.get('name', None)
      key = (child_name, child_path)
      if key in self._variant_children_by_name_and_path:
        raise ValueError, 'Found multiple PBXVariantGroup children with ' + \
                          'name ' + str(child_name) + ' and path ' + \
                          str(child_path)
      self._variant_children_by_name_and_path[key] = child

  def AppendChild(self, child):
    # Callers should use this instead of calling
    # AppendProperty('children', child) directly because this function
    # maintains the group's dicts.
    self.AppendProperty('children', child)
    self._AddChildToDicts(child)

  def GetChildByName(self, name):
    # This is not currently optimized with a dict as GetChildByPath is because
    # it has few callers.  Most callers probably want GetChildByPath.  This
    # function is only useful to get children that have names but no paths,
    # which is rare.  The children of the main group ("Source", "Products",
    # etc.) is pretty much the only case where this likely to come up.
    #
    # TODO(mark): Maybe this should raise an error if more than one child is
    # present with the same name.
    if not 'children' in self._properties:
      return None

    for child in self._properties['children']:
      if child.Name() == name:
        return child

    return None

  def GetChildByPath(self, path):
    if not path:
      return None

    if path in self._children_by_path:
      return self._children_by_path[path]

    return None

  def GetChildByRemoteObject(self, remote_object):
    # This method is a little bit esoteric.  Given a remote_object, which
    # should be a PBXFileReference in another project file, this method will
    # return this group's PBXReferenceProxy object serving as a local proxy
    # for the remote PBXFileReference.
    #
    # This function might benefit from a dict optimization as GetChildByPath
    # for some workloads, but profiling shows that it's not currently a
    # problem.
    if not 'children' in self._properties:
      return None

    for child in self._properties['children']:
      if not isinstance(child, PBXReferenceProxy):
        continue

      container_proxy = child._properties['remoteRef']
      if container_proxy._properties['remoteGlobalIDString'] == remote_object:
        return child

    return None

  def AddOrGetFileByPath(self, path, hierarchical):
    """Returns an existing or new file reference corresponding to path.

    If hierarchical is True, this method will create or use the necessary
    hierarchical group structure corresponding to path.  Otherwise, it will
    look in and create an item in the current group only.

    If an existing matching reference is found, it is returned, otherwise, a
    new one will be created, added to the correct group, and returned.

    If path identifies a directory by virtue of carrying a trailing slash,
    this method returns a PBXFileReference of "folder" type.  If path
    identifies a variant, by virtue of it identifying a file inside a directory
    with an ".lproj" extension, this method returns a PBXVariantGroup
    containing the variant named by path, and possibly other variants.  For
    all other paths, a "normal" PBXFileReference will be returned.
    """

    # Adding or getting a directory?  Directories end with a trailing slash.
    is_dir = False
    if path.endswith('/'):
      is_dir = True
    path = posixpath.normpath(path)
    if is_dir:
      path = path + '/'

    # Adding or getting a variant?  Variants are files inside directories
    # with an ".lproj" extension.  Xcode uses variants for localization.  For
    # a variant path/to/Language.lproj/MainMenu.nib, put a variant group named
    # MainMenu.nib inside path/to, and give it a variant named Language.  In
    # this example, grandparent would be set to path/to and parent_root would
    # be set to Language.
    variant_name = None
    parent = posixpath.dirname(path)
    grandparent = posixpath.dirname(parent)
    parent_basename = posixpath.basename(parent)
    (parent_root, parent_ext) = posixpath.splitext(parent_basename)
    if parent_ext == '.lproj':
      variant_name = parent_root
    if grandparent == '':
      grandparent = None

    # Putting a directory inside a variant group is not currently supported.
    assert not is_dir or variant_name is None

    path_split = path.split(posixpath.sep)
    if len(path_split) == 1 or \
       ((is_dir or variant_name != None) and len(path_split) == 2) or \
       not hierarchical:
      # The PBXFileReference or PBXVariantGroup will be added to or gotten from
      # this PBXGroup, no recursion necessary.
      if variant_name is None:
        # Add or get a PBXFileReference.
        file_ref = self.GetChildByPath(path)
        if file_ref != None:
          assert file_ref.__class__ == PBXFileReference
        else:
          file_ref = PBXFileReference({'path': path})
          self.AppendChild(file_ref)
      else:
        # Add or get a PBXVariantGroup.  The variant group name is the same
        # as the basename (MainMenu.nib in the example above).  grandparent
        # specifies the path to the variant group itself, and path_split[-2:]
        # is the path of the specific variant relative to its group.
        variant_group_name = posixpath.basename(path)
        variant_group_ref = self.AddOrGetVariantGroupByNameAndPath(
            variant_group_name, grandparent)
        variant_path = posixpath.sep.join(path_split[-2:])
        variant_ref = variant_group_ref.GetChildByPath(variant_path)
        if variant_ref != None:
          assert variant_ref.__class__ == PBXFileReference
        else:
          variant_ref = PBXFileReference({'name': variant_name,
                                          'path': variant_path})
          variant_group_ref.AppendChild(variant_ref)
        # The caller is interested in the variant group, not the specific
        # variant file.
        file_ref = variant_group_ref
      return file_ref
    else:
      # Hierarchical recursion.  Add or get a PBXGroup corresponding to the
      # outermost path component, and then recurse into it, chopping off that
      # path component.
      next_dir = path_split[0]
      group_ref = self.GetChildByPath(next_dir)
      if group_ref != None:
        assert group_ref.__class__ == PBXGroup
      else:
        group_ref = PBXGroup({'path': next_dir})
        self.AppendChild(group_ref)
      return group_ref.AddOrGetFileByPath(posixpath.sep.join(path_split[1:]),
                                          hierarchical)

  def AddOrGetVariantGroupByNameAndPath(self, name, path):
    """Returns an existing or new PBXVariantGroup for name and path.

    If a PBXVariantGroup identified by the name and path arguments is already
    present as a child of this object, it is returned.  Otherwise, a new
    PBXVariantGroup with the correct properties is created, added as a child,
    and returned.

    This method will generally be called by AddOrGetFileByPath, which knows
    when to create a variant group based on the structure of the pathnames
    passed to it.
    """

    key = (name, path)
    if key in self._variant_children_by_name_and_path:
      variant_group_ref = self._variant_children_by_name_and_path[key]
      assert variant_group_ref.__class__ == PBXVariantGroup
      return variant_group_ref

    variant_group_properties = {'name': name}
    if path != None:
      variant_group_properties['path'] = path
    variant_group_ref = PBXVariantGroup(variant_group_properties)
    self.AppendChild(variant_group_ref)

    return variant_group_ref

  def TakeOverOnlyChild(self, recurse=False):
    """If this PBXGroup has only one child and it's also a PBXGroup, take
    it over by making all of its children this object's children.

    This function will continue to take over only children when those children
    are groups.  If there are three PBXGroups representing a, b, and c, with
    c inside b and b inside a, and a and b have no other children, this will
    result in a taking over both b and c, forming a PBXGroup for a/b/c.

    If recurse is True, this function will recurse into children and ask them
    to collapse themselves by taking over only children as well.  Assuming
    an example hierarchy with files at a/b/c/d1, a/b/c/d2, and a/b/c/d3/e/f
    (d1, d2, and f are files, the rest are groups), recursion will result in
    a group for a/b/c containing a group for d3/e.
    """

    # At this stage, check that child class types are PBXGroup exactly,
    # instead of using isinstance.  The only subclass of PBXGroup,
    # PBXVariantGroup, should not participate in reparenting in the same way:
    # reparenting by merging different object types would be wrong.
    while len(self._properties['children']) == 1 and \
          self._properties['children'][0].__class__ == PBXGroup:
      # Loop to take over the innermost only-child group possible.

      child = self._properties['children'][0]

      # Assume the child's properties, including its children.  Save a copy
      # of this object's old properties, because they'll still be needed.
      # This object retains its existing id and parent attributes.
      old_properties = self._properties
      self._properties = child._properties
      self._children_by_path = child._children_by_path

      if not 'sourceTree' in self._properties or \
         self._properties['sourceTree'] == '<group>':
        # The child was relative to its parent.  Fix up the path.  Note that
        # children with a sourceTree other than "<group>" are not relative to
        # their parents, so no path fix-up is needed in that case.
        if 'path' in old_properties:
          if 'path' in self._properties:
            # Both the original parent and child have paths set.
            self._properties['path'] = posixpath.join(old_properties['path'],
                                                      self._properties['path'])
          else:
            # Only the original parent has a path, use it.
            self._properties['path'] = old_properties['path']
        if 'sourceTree' in old_properties:
          # The original parent had a sourceTree set, use it.
          self._properties['sourceTree'] = old_properties['sourceTree']

      # If the original parent had a name set, keep using it.  If the original
      # parent didn't have a name but the child did, let the child's name
      # live on.  If the name attribute seems unnecessary now, get rid of it.
      if 'name' in old_properties and old_properties['name'] != None and \
         old_properties['name'] != self.Name():
        self._properties['name'] = old_properties['name']
      if 'name' in self._properties and 'path' in self._properties and \
         self._properties['name'] == self._properties['path']:
        del self._properties['name']

      # Notify all children of their new parent.
      for child in self._properties['children']:
        child.parent = self

    # If asked to recurse, recurse.
    if recurse:
      for child in self._properties['children']:
        if child.__class__ == PBXGroup:
          child.TakeOverOnlyChild(recurse)

  def SortGroup(self):
    self._properties['children'] = \
        sorted(self._properties['children'], cmp=lambda x,y: x.Compare(y))

    # Recurse.
    for child in self._properties['children']:
      if isinstance(child, PBXGroup):
        child.SortGroup()


class XCFileLikeElement(XCHierarchicalElement):
  # Abstract base for objects that can be used as the fileRef property of
  # PBXBuildFile.

  def PathHashables(self):
    # A PBXBuildFile that refers to this object will call this method to
    # obtain additional hashables specific to this XCFileLikeElement.  Don't
    # just use this object's hashables, they're not specific and unique enough
    # on their own (without access to the parent hashables.)  Instead, provide
    # hashables that identify this object by path by getting its hashables as
    # well as the hashables of ancestor XCHierarchicalElement objects.

    hashables = []
    xche = self
    while xche != None and isinstance(xche, XCHierarchicalElement):
      xche_hashables = xche.Hashables()
      for index in xrange(0, len(xche_hashables)):
        hashables.insert(index, xche_hashables[index])
      xche = xche.parent
    return hashables


class XCContainerPortal(XCObject):
  # Abstract base for objects that can be used as the containerPortal property
  # of PBXContainerItemProxy.
  pass


class XCRemoteObject(XCObject):
  # Abstract base for objects that can be used as the remoteGlobalIDString
  # property of PBXContainerItemProxy.
  pass


class PBXFileReference(XCFileLikeElement, XCContainerPortal, XCRemoteObject):
  _schema = XCFileLikeElement._schema.copy()
  _schema.update({
    'explicitFileType':  [0, str, 0, 0],
    'lastKnownFileType': [0, str, 0, 0],
    'name':              [0, str, 0, 0],
    'path':              [0, str, 0, 1],
  })

  # Weird output rules for PBXFileReference.
  _should_print_single_line = True
  # super
  _encode_transforms = XCFileLikeElement._alternate_encode_transforms

  def __init__(self, properties=None, id=None, parent=None):
    # super
    XCFileLikeElement.__init__(self, properties, id, parent)
    if 'path' in self._properties and self._properties['path'].endswith('/'):
      self._properties['path'] = self._properties['path'][:-1]
      is_dir = True
    else:
      is_dir = False

    if 'path' in self._properties and \
        not 'lastKnownFileType' in self._properties and \
        not 'explicitFileType' in self._properties:
      # TODO(mark): This is the replacement for a replacement for a quick hack.
      # It is no longer incredibly sucky, but this list needs to be extended.
      extension_map = {
        'a':           'archive.ar',
        'app':         'wrapper.application',
        'bdic':        'file',
        'bundle':      'wrapper.cfbundle',
        'c':           'sourcecode.c.c',
        'cc':          'sourcecode.cpp.cpp',
        'cpp':         'sourcecode.cpp.cpp',
        'css':         'text.css',
        'cxx':         'sourcecode.cpp.cpp',
        'dart':        'sourcecode',
        'dylib':       'compiled.mach-o.dylib',
        'framework':   'wrapper.framework',
        'gyp':         'sourcecode',
        'gypi':        'sourcecode',
        'h':           'sourcecode.c.h',
        'hxx':         'sourcecode.cpp.h',
        'icns':        'image.icns',
        'java':        'sourcecode.java',
        'js':          'sourcecode.javascript',
        'm':           'sourcecode.c.objc',
        'mm':          'sourcecode.cpp.objcpp',
        'nib':         'wrapper.nib',
        'o':           'compiled.mach-o.objfile',
        'pdf':         'image.pdf',
        'pl':          'text.script.perl',
        'plist':       'text.plist.xml',
        'pm':          'text.script.perl',
        'png':         'image.png',
        'py':          'text.script.python',
        'r':           'sourcecode.rez',
        'rez':         'sourcecode.rez',
        's':           'sourcecode.asm',
        'storyboard':  'file.storyboard',
        'strings':     'text.plist.strings',
        'swift':       'sourcecode.swift',
        'ttf':         'file',
        'xcassets':    'folder.assetcatalog',
        'xcconfig':    'text.xcconfig',
        'xcdatamodel': 'wrapper.xcdatamodel',
        'xcdatamodeld':'wrapper.xcdatamodeld',
        'xib':         'file.xib',
        'y':           'sourcecode.yacc',
      }

      prop_map = {
        'dart':        'explicitFileType',
        'gyp':         'explicitFileType',
        'gypi':        'explicitFileType',
      }

      if is_dir:
        file_type = 'folder'
        prop_name = 'lastKnownFileType'
      else:
        basename = posixpath.basename(self._properties['path'])
        (root, ext) = posixpath.splitext(basename)
        # Check the map using a lowercase extension.
        # TODO(mark): Maybe it should try with the original case first and fall
        # back to lowercase, in case there are any instances where case
        # matters.  There currently aren't.
        if ext != '':
          ext = ext[1:].lower()

        # TODO(mark): "text" is the default value, but "file" is appropriate
        # for unrecognized files not containing text.  Xcode seems to choose
        # based on content.
        file_type = extension_map.get(ext, 'text')
        prop_name = prop_map.get(ext, 'lastKnownFileType')

      self._properties[prop_name] = file_type


class PBXVariantGroup(PBXGroup, XCFileLikeElement):
  """PBXVariantGroup is used by Xcode to represent localizations."""
  # No additions to the schema relative to PBXGroup.
  pass


# PBXReferenceProxy is also an XCFileLikeElement subclass.  It is defined below
# because it uses PBXContainerItemProxy, defined below.


class XCBuildConfiguration(XCObject):
  _schema = XCObject._schema.copy()
  _schema.update({
    'baseConfigurationReference': [0, PBXFileReference, 0, 0],
    'buildSettings':              [0, dict, 0, 1, {}],
    'name':                       [0, str,  0, 1],
  })

  def HasBuildSetting(self, key):
    return key in self._properties['buildSettings']

  def GetBuildSetting(self, key):
    return self._properties['buildSettings'][key]

  def SetBuildSetting(self, key, value):
    # TODO(mark): If a list, copy?
    self._properties['buildSettings'][key] = value

  def AppendBuildSetting(self, key, value):
    if not key in self._properties['buildSettings']:
      self._properties['buildSettings'][key] = []
    self._properties['buildSettings'][key].append(value)

  def DelBuildSetting(self, key):
    if key in self._properties['buildSettings']:
      del self._properties['buildSettings'][key]

  def SetBaseConfiguration(self, value):
    self._properties['baseConfigurationReference'] = value

class XCConfigurationList(XCObject):
  # _configs is the default list of configurations.
  _configs = [ XCBuildConfiguration({'name': 'Debug'}),
               XCBuildConfiguration({'name': 'Release'}) ]

  _schema = XCObject._schema.copy()
  _schema.update({
    'buildConfigurations':           [1, XCBuildConfiguration, 1, 1, _configs],
    'defaultConfigurationIsVisible': [0, int,                  0, 1, 1],
    'defaultConfigurationName':      [0, str,                  0, 1, 'Release'],
  })

  def Name(self):
    return 'Build configuration list for ' + \
           self.parent.__class__.__name__ + ' "' + self.parent.Name() + '"'

  def ConfigurationNamed(self, name):
    """Convenience accessor to obtain an XCBuildConfiguration by name."""
    for configuration in self._properties['buildConfigurations']:
      if configuration._properties['name'] == name:
        return configuration

    raise KeyError, name

  def DefaultConfiguration(self):
    """Convenience accessor to obtain the default XCBuildConfiguration."""
    return self.ConfigurationNamed(self._properties['defaultConfigurationName'])

  def HasBuildSetting(self, key):
    """Determines the state of a build setting in all XCBuildConfiguration
    child objects.

    If all child objects have key in their build settings, and the value is the
    same in all child objects, returns 1.

    If no child objects have the key in their build settings, returns 0.

    If some, but not all, child objects have the key in their build settings,
    or if any children have different values for the key, returns -1.
    """

    has = None
    value = None
    for configuration in self._properties['buildConfigurations']:
      configuration_has = configuration.HasBuildSetting(key)
      if has is None:
        has = configuration_has
      elif has != configuration_has:
        return -1

      if configuration_has:
        configuration_value = configuration.GetBuildSetting(key)
        if value is None:
          value = configuration_value
        elif value != configuration_value:
          return -1

    if not has:
      return 0

    return 1

  def GetBuildSetting(self, key):
    """Gets the build setting for key.

    All child XCConfiguration objects must have the same value set for the
    setting, or a ValueError will be raised.
    """

    # TODO(mark): This is wrong for build settings that are lists.  The list
    # contents should be compared (and a list copy returned?)

    value = None
    for configuration in self._properties['buildConfigurations']:
      configuration_value = configuration.GetBuildSetting(key)
      if value is None:
        value = configuration_value
      else:
        if value != configuration_value:
          raise ValueError, 'Variant values for ' + key

    return value

  def SetBuildSetting(self, key, value):
    """Sets the build setting for key to value in all child
    XCBuildConfiguration objects.
    """

    for configuration in self._properties['buildConfigurations']:
      configuration.SetBuildSetting(key, value)

  def AppendBuildSetting(self, key, value):
    """Appends value to the build setting for key, which is treated as a list,
    in all child XCBuildConfiguration objects.
    """

    for configuration in self._properties['buildConfigurations']:
      configuration.AppendBuildSetting(key, value)

  def DelBuildSetting(self, key):
    """Deletes the build setting key from all child XCBuildConfiguration
    objects.
    """

    for configuration in self._properties['buildConfigurations']:
      configuration.DelBuildSetting(key)

  def SetBaseConfiguration(self, value):
    """Sets the build configuration in all child XCBuildConfiguration objects.
    """

    for configuration in self._properties['buildConfigurations']:
      configuration.SetBaseConfiguration(value)


class PBXBuildFile(XCObject):
  _schema = XCObject._schema.copy()
  _schema.update({
    'fileRef':  [0, XCFileLikeElement, 0, 1],
    'settings': [0, str,               0, 0],  # hack, it's a dict
  })

  # Weird output rules for PBXBuildFile.
  _should_print_single_line = True
  _encode_transforms = XCObject._alternate_encode_transforms

  def Name(self):
    # Example: "main.cc in Sources"
    return self._properties['fileRef'].Name() + ' in ' + self.parent.Name()

  def Hashables(self):
    # super
    hashables = XCObject.Hashables(self)

    # It is not sufficient to just rely on Name() to get the
    # XCFileLikeElement's name, because that is not a complete pathname.
    # PathHashables returns hashables unique enough that no two
    # PBXBuildFiles should wind up with the same set of hashables, unless
    # someone adds the same file multiple times to the same target.  That
    # would be considered invalid anyway.
    hashables.extend(self._properties['fileRef'].PathHashables())

    return hashables


class XCBuildPhase(XCObject):
  """Abstract base for build phase classes.  Not represented in a project
  file.

  Attributes:
    _files_by_path: A dict mapping each path of a child in the files list by
      path (keys) to the corresponding PBXBuildFile children (values).
    _files_by_xcfilelikeelement: A dict mapping each XCFileLikeElement (keys)
      to the corresponding PBXBuildFile children (values).
  """

  # TODO(mark): Some build phase types, like PBXShellScriptBuildPhase, don't
  # actually have a "files" list.  XCBuildPhase should not have "files" but
  # another abstract subclass of it should provide this, and concrete build
  # phase types that do have "files" lists should be derived from that new
  # abstract subclass.  XCBuildPhase should only provide buildActionMask and
  # runOnlyForDeploymentPostprocessing, and not files or the various
  # file-related methods and attributes.

  _schema = XCObject._schema.copy()
  _schema.update({
    'buildActionMask':                    [0, int,          0, 1, 0x7fffffff],
    'files':                              [1, PBXBuildFile, 1, 1, []],
    'runOnlyForDeploymentPostprocessing': [0, int,          0, 1, 0],
  })

  def __init__(self, properties=None, id=None, parent=None):
    # super
    XCObject.__init__(self, properties, id, parent)

    self._files_by_path = {}
    self._files_by_xcfilelikeelement = {}
    for pbxbuildfile in self._properties.get('files', []):
      self._AddBuildFileToDicts(pbxbuildfile)

  def FileGroup(self, path):
    # Subclasses must override this by returning a two-element tuple.  The
    # first item in the tuple should be the PBXGroup to which "path" should be
    # added, either as a child or deeper descendant.  The second item should
    # be a boolean indicating whether files should be added into hierarchical
    # groups or one single flat group.
    raise NotImplementedError, \
          self.__class__.__name__ + ' must implement FileGroup'

  def _AddPathToDict(self, pbxbuildfile, path):
    """Adds path to the dict tracking paths belonging to this build phase.

    If the path is already a member of this build phase, raises an exception.
    """

    if path in self._files_by_path:
      raise ValueError, 'Found multiple build files with path ' + path
    self._files_by_path[path] = pbxbuildfile

  def _AddBuildFileToDicts(self, pbxbuildfile, path=None):
    """Maintains the _files_by_path and _files_by_xcfilelikeelement dicts.

    If path is specified, then it is the path that is being added to the
    phase, and pbxbuildfile must contain either a PBXFileReference directly
    referencing that path, or it must contain a PBXVariantGroup that itself
    contains a PBXFileReference referencing the path.

    If path is not specified, either the PBXFileReference's path or the paths
    of all children of the PBXVariantGroup are taken as being added to the
    phase.

    If the path is already present in the phase, raises an exception.

    If the PBXFileReference or PBXVariantGroup referenced by pbxbuildfile
    are already present in the phase, referenced by a different PBXBuildFile
    object, raises an exception.  This does not raise an exception when
    a PBXFileReference or PBXVariantGroup reappear and are referenced by the
    same PBXBuildFile that has already introduced them, because in the case
    of PBXVariantGroup objects, they may correspond to multiple paths that are
    not all added simultaneously.  When this situation occurs, the path needs
    to be added to _files_by_path, but nothing needs to change in
    _files_by_xcfilelikeelement, and the caller should have avoided adding
    the PBXBuildFile if it is already present in the list of children.
    """

    xcfilelikeelement = pbxbuildfile._properties['fileRef']

    paths = []
    if path != None:
      # It's best when the caller provides the path.
      if isinstance(xcfilelikeelement, PBXVariantGroup):
        paths.append(path)
    else:
      # If the caller didn't provide a path, there can be either multiple
      # paths (PBXVariantGroup) or one.
      if isinstance(xcfilelikeelement, PBXVariantGroup):
        for variant in xcfilelikeelement._properties['children']:
          paths.append(variant.FullPath())
      else:
        paths.append(xcfilelikeelement.FullPath())

    # Add the paths first, because if something's going to raise, the
    # messages provided by _AddPathToDict are more useful owing to its
    # having access to a real pathname and not just an object's Name().
    for a_path in paths:
      self._AddPathToDict(pbxbuildfile, a_path)

    # If another PBXBuildFile references this XCFileLikeElement, there's a
    # problem.
    if xcfilelikeelement in self._files_by_xcfilelikeelement and \
       self._files_by_xcfilelikeelement[xcfilelikeelement] != pbxbuildfile:
      raise ValueError, 'Found multiple build files for ' + \
                        xcfilelikeelement.Name()
    self._files_by_xcfilelikeelement[xcfilelikeelement] = pbxbuildfile

  def AppendBuildFile(self, pbxbuildfile, path=None):
    # Callers should use this instead of calling
    # AppendProperty('files', pbxbuildfile) directly because this function
    # maintains the object's dicts.  Better yet, callers can just call AddFile
    # with a pathname and not worry about building their own PBXBuildFile
    # objects.
    self.AppendProperty('files', pbxbuildfile)
    self._AddBuildFileToDicts(pbxbuildfile, path)

  def AddFile(self, path, settings=None):
    (file_group, hierarchical) = self.FileGroup(path)
    file_ref = file_group.AddOrGetFileByPath(path, hierarchical)

    if file_ref in self._files_by_xcfilelikeelement and \
       isinstance(file_ref, PBXVariantGroup):
      # There's already a PBXBuildFile in this phase corresponding to the
      # PBXVariantGroup.  path just provides a new variant that belongs to
      # the group.  Add the path to the dict.
      pbxbuildfile = self._files_by_xcfilelikeelement[file_ref]
      self._AddBuildFileToDicts(pbxbuildfile, path)
    else:
      # Add a new PBXBuildFile to get file_ref into the phase.
      if settings is None:
        pbxbuildfile = PBXBuildFile({'fileRef': file_ref})
      else:
        pbxbuildfile = PBXBuildFile({'fileRef': file_ref, 'settings': settings})
      self.AppendBuildFile(pbxbuildfile, path)


class PBXHeadersBuildPhase(XCBuildPhase):
  # No additions to the schema relative to XCBuildPhase.

  def Name(self):
    return 'Headers'

  def FileGroup(self, path):
    return self.PBXProjectAncestor().RootGroupForPath(path)


class PBXResourcesBuildPhase(XCBuildPhase):
  # No additions to the schema relative to XCBuildPhase.

  def Name(self):
    return 'Resources'

  def FileGroup(self, path):
    return self.PBXProjectAncestor().RootGroupForPath(path)


class PBXSourcesBuildPhase(XCBuildPhase):
  # No additions to the schema relative to XCBuildPhase.

  def Name(self):
    return 'Sources'

  def FileGroup(self, path):
    return self.PBXProjectAncestor().RootGroupForPath(path)


class PBXFrameworksBuildPhase(XCBuildPhase):
  # No additions to the schema relative to XCBuildPhase.

  def Name(self):
    return 'Frameworks'

  def FileGroup(self, path):
    (root, ext) = posixpath.splitext(path)
    if ext != '':
      ext = ext[1:].lower()
    if ext == 'o':
      # .o files are added to Xcode Frameworks phases, but conceptually aren't
      # frameworks, they're more like sources or intermediates. Redirect them
      # to show up in one of those other groups.
      return self.PBXProjectAncestor().RootGroupForPath(path)
    else:
      return (self.PBXProjectAncestor().FrameworksGroup(), False)


class PBXShellScriptBuildPhase(XCBuildPhase):
  _schema = XCBuildPhase._schema.copy()
  _schema.update({
    'inputPaths':       [1, str, 0, 1, []],
    'name':             [0, str, 0, 0],
    'outputPaths':      [1, str, 0, 1, []],
    'shellPath':        [0, str, 0, 1, '/bin/sh'],
    'shellScript':      [0, str, 0, 1],
    'showEnvVarsInLog': [0, int, 0, 0],
  })

  def Name(self):
    if 'name' in self._properties:
      return self._properties['name']

    return 'ShellScript'


class PBXCopyFilesBuildPhase(XCBuildPhase):
  _schema = XCBuildPhase._schema.copy()
  _schema.update({
    'dstPath':          [0, str, 0, 1],
    'dstSubfolderSpec': [0, int, 0, 1],
    'name':             [0, str, 0, 0],
  })

  # path_tree_re matches "$(DIR)/path" or just "$(DIR)".  Match group 1 is
  # "DIR", match group 3 is "path" or None.
  path_tree_re = re.compile('^\\$\\((.*)\\)(/(.*)|)$')

  # path_tree_to_subfolder maps names of Xcode variables to the associated
  # dstSubfolderSpec property value used in a PBXCopyFilesBuildPhase object.
  path_tree_to_subfolder = {
    'BUILT_PRODUCTS_DIR': 16,  # Products Directory
    # Other types that can be chosen via the Xcode UI.
    # TODO(mark): Map Xcode variable names to these.
    # : 1,  # Wrapper
    # : 6,  # Executables: 6
    # : 7,  # Resources
    # : 15,  # Java Resources
    # : 10,  # Frameworks
    # : 11,  # Shared Frameworks
    # : 12,  # Shared Support
    # : 13,  # PlugIns
  }

  def Name(self):
    if 'name' in self._properties:
      return self._properties['name']

    return 'CopyFiles'

  def FileGroup(self, path):
    return self.PBXProjectAncestor().RootGroupForPath(path)

  def SetDestination(self, path):
    """Set the dstSubfolderSpec and dstPath properties from path.

    path may be specified in the same notation used for XCHierarchicalElements,
    specifically, "$(DIR)/path".
    """

    path_tree_match = self.path_tree_re.search(path)
    if path_tree_match:
      # Everything else needs to be relative to an Xcode variable.
      path_tree = path_tree_match.group(1)
      relative_path = path_tree_match.group(3)

      if path_tree in self.path_tree_to_subfolder:
        subfolder = self.path_tree_to_subfolder[path_tree]
        if relative_path is None:
          relative_path = ''
      else:
        # The path starts with an unrecognized Xcode variable
        # name like $(SRCROOT).  Xcode will still handle this
        # as an "absolute path" that starts with the variable.
        subfolder = 0
        relative_path = path
    elif path.startswith('/'):
      # Special case.  Absolute paths are in dstSubfolderSpec 0.
      subfolder = 0
      relative_path = path[1:]
    else:
      raise ValueError, 'Can\'t use path %s in a %s' % \
                        (path, self.__class__.__name__)

    self._properties['dstPath'] = relative_path
    self._properties['dstSubfolderSpec'] = subfolder


class PBXBuildRule(XCObject):
  _schema = XCObject._schema.copy()
  _schema.update({
    'compilerSpec': [0, str, 0, 1],
    'filePatterns': [0, str, 0, 0],
    'fileType':     [0, str, 0, 1],
    'isEditable':   [0, int, 0, 1, 1],
    'outputFiles':  [1, str, 0, 1, []],
    'script':       [0, str, 0, 0],
  })

  def Name(self):
    # Not very inspired, but it's what Xcode uses.
    return self.__class__.__name__

  def Hashables(self):
    # super
    hashables = XCObject.Hashables(self)

    # Use the hashables of the weak objects that this object refers to.
    hashables.append(self._properties['fileType'])
    if 'filePatterns' in self._properties:
      hashables.append(self._properties['filePatterns'])
    return hashables


class PBXContainerItemProxy(XCObject):
  # When referencing an item in this project file, containerPortal is the
  # PBXProject root object of this project file.  When referencing an item in
  # another project file, containerPortal is a PBXFileReference identifying
  # the other project file.
  #
  # When serving as a proxy to an XCTarget (in this project file or another),
  # proxyType is 1.  When serving as a proxy to a PBXFileReference (in another
  # project file), proxyType is 2.  Type 2 is used for references to the
  # producs of the other project file's targets.
  #
  # Xcode is weird about remoteGlobalIDString.  Usually, it's printed without
  # a comment, indicating that it's tracked internally simply as a string, but
  # sometimes it's printed with a comment (usually when the object is initially
  # created), indicating that it's tracked as a project file object at least
  # sometimes.  This module always tracks it as an object, but contains a hack
  # to prevent it from printing the comment in the project file output.  See
  # _XCKVPrint.
  _schema = XCObject._schema.copy()
  _schema.update({
    'containerPortal':      [0, XCContainerPortal, 0, 1],
    'proxyType':            [0, int,               0, 1],
    'remoteGlobalIDString': [0, XCRemoteObject,    0, 1],
    'remoteInfo':           [0, str,               0, 1],
  })

  def __repr__(self):
    props = self._properties
    name = '%s.gyp:%s' % (props['containerPortal'].Name(), props['remoteInfo'])
    return '<%s %r at 0x%x>' % (self.__class__.__name__, name, id(self))

  def Name(self):
    # Admittedly not the best name, but it's what Xcode uses.
    return self.__class__.__name__

  def Hashables(self):
    # super
    hashables = XCObject.Hashables(self)

    # Use the hashables of the weak objects that this object refers to.
    hashables.extend(self._properties['containerPortal'].Hashables())
    hashables.extend(self._properties['remoteGlobalIDString'].Hashables())
    return hashables


class PBXTargetDependency(XCObject):
  # The "target" property accepts an XCTarget object, and obviously not
  # NoneType.  But XCTarget is defined below, so it can't be put into the
  # schema yet.  The definition of PBXTargetDependency can't be moved below
  # XCTarget because XCTarget's own schema references PBXTargetDependency.
  # Python doesn't deal well with this circular relationship, and doesn't have
  # a real way to do forward declarations.  To work around, the type of
  # the "target" property is reset below, after XCTarget is defined.
  #
  # At least one of "name" and "target" is required.
  _schema = XCObject._schema.copy()
  _schema.update({
    'name':        [0, str,                   0, 0],
    'target':      [0, None.__class__,        0, 0],
    'targetProxy': [0, PBXContainerItemProxy, 1, 1],
  })

  def __repr__(self):
    name = self._properties.get('name') or self._properties['target'].Name()
    return '<%s %r at 0x%x>' % (self.__class__.__name__, name, id(self))

  def Name(self):
    # Admittedly not the best name, but it's what Xcode uses.
    return self.__class__.__name__

  def Hashables(self):
    # super
    hashables = XCObject.Hashables(self)

    # Use the hashables of the weak objects that this object refers to.
    hashables.extend(self._properties['targetProxy'].Hashables())
    return hashables


class PBXReferenceProxy(XCFileLikeElement):
  _schema = XCFileLikeElement._schema.copy()
  _schema.update({
    'fileType':  [0, str,                   0, 1],
    'path':      [0, str,                   0, 1],
    'remoteRef': [0, PBXContainerItemProxy, 1, 1],
  })


class XCTarget(XCRemoteObject):
  # An XCTarget is really just an XCObject, the XCRemoteObject thing is just
  # to allow PBXProject to be used in the remoteGlobalIDString property of
  # PBXContainerItemProxy.
  #
  # Setting a "name" property at instantiation may also affect "productName",
  # which may in turn affect the "PRODUCT_NAME" build setting in children of
  # "buildConfigurationList".  See __init__ below.
  _schema = XCRemoteObject._schema.copy()
  _schema.update({
    'buildConfigurationList': [0, XCConfigurationList, 1, 1,
                               XCConfigurationList()],
    'buildPhases':            [1, XCBuildPhase,        1, 1, []],
    'dependencies':           [1, PBXTargetDependency, 1, 1, []],
    'name':                   [0, str,                 0, 1],
    'productName':            [0, str,                 0, 1],
  })

  def __init__(self, properties=None, id=None, parent=None,
               force_outdir=None, force_prefix=None, force_extension=None):
    # super
    XCRemoteObject.__init__(self, properties, id, parent)

    # Set up additional defaults not expressed in the schema.  If a "name"
    # property was supplied, set "productName" if it is not present.  Also set
    # the "PRODUCT_NAME" build setting in each configuration, but only if
    # the setting is not present in any build configuration.
    if 'name' in self._properties:
      if not 'productName' in self._properties:
        self.SetProperty('productName', self._properties['name'])

    if 'productName' in self._properties:
      if 'buildConfigurationList' in self._properties:
        configs = self._properties['buildConfigurationList']
        if configs.HasBuildSetting('PRODUCT_NAME') == 0:
          configs.SetBuildSetting('PRODUCT_NAME',
                                  self._properties['productName'])

  def AddDependency(self, other):
    pbxproject = self.PBXProjectAncestor()
    other_pbxproject = other.PBXProjectAncestor()
    if pbxproject == other_pbxproject:
      # Add a dependency to another target in the same project file.
      container = PBXContainerItemProxy({'containerPortal':      pbxproject,
                                         'proxyType':            1,
                                         'remoteGlobalIDString': other,
                                         'remoteInfo':           other.Name()})
      dependency = PBXTargetDependency({'target':      other,
                                        'targetProxy': container})
      self.AppendProperty('dependencies', dependency)
    else:
      # Add a dependency to a target in a different project file.
      other_project_ref = \
          pbxproject.AddOrGetProjectReference(other_pbxproject)[1]
      container = PBXContainerItemProxy({
            'containerPortal':      other_project_ref,
            'proxyType':            1,
            'remoteGlobalIDString': other,
            'remoteInfo':           other.Name(),
          })
      dependency = PBXTargetDependency({'name':        other.Name(),
                                        'targetProxy': container})
      self.AppendProperty('dependencies', dependency)

  # Proxy all of these through to the build configuration list.

  def ConfigurationNamed(self, name):
    return self._properties['buildConfigurationList'].ConfigurationNamed(name)

  def DefaultConfiguration(self):
    return self._properties['buildConfigurationList'].DefaultConfiguration()

  def HasBuildSetting(self, key):
    return self._properties['buildConfigurationList'].HasBuildSetting(key)

  def GetBuildSetting(self, key):
    return self._properties['buildConfigurationList'].GetBuildSetting(key)

  def SetBuildSetting(self, key, value):
    return self._properties['buildConfigurationList'].SetBuildSetting(key, \
                                                                      value)

  def AppendBuildSetting(self, key, value):
    return self._properties['buildConfigurationList'].AppendBuildSetting(key, \
                                                                         value)

  def DelBuildSetting(self, key):
    return self._properties['buildConfigurationList'].DelBuildSetting(key)


# Redefine the type of the "target" property.  See PBXTargetDependency._schema
# above.
PBXTargetDependency._schema['target'][1] = XCTarget


class PBXNativeTarget(XCTarget):
  # buildPhases is overridden in the schema to be able to set defaults.
  #
  # NOTE: Contrary to most objects, it is advisable to set parent when
  # constructing PBXNativeTarget.  A parent of an XCTarget must be a PBXProject
  # object.  A parent reference is required for a PBXNativeTarget during
  # construction to be able to set up the target defaults for productReference,
  # because a PBXBuildFile object must be created for the target and it must
  # be added to the PBXProject's mainGroup hierarchy.
  _schema = XCTarget._schema.copy()
  _schema.update({
    'buildPhases':      [1, XCBuildPhase,     1, 1,
                         [PBXSourcesBuildPhase(), PBXFrameworksBuildPhase()]],
    'buildRules':       [1, PBXBuildRule,     1, 1, []],
    'productReference': [0, PBXFileReference, 0, 1],
    'productType':      [0, str,              0, 1],
  })

  # Mapping from Xcode product-types to settings.  The settings are:
  #  filetype : used for explicitFileType in the project file
  #  prefix : the prefix for the file name
  #  suffix : the suffix for the file name
  _product_filetypes = {
    'com.apple.product-type.application':       ['wrapper.application',
                                                 '', '.app'],
    'com.apple.product-type.app-extension':     ['wrapper.app-extension',
                                                 '', '.appex'],
    'com.apple.product-type.bundle':            ['wrapper.cfbundle',
                                                 '', '.bundle'],
    'com.apple.product-type.framework':         ['wrapper.framework',
                                                 '', '.framework'],
    'com.apple.product-type.library.dynamic':   ['compiled.mach-o.dylib',
                                                 'lib', '.dylib'],
    'com.apple.product-type.library.static':    ['archive.ar',
                                                 'lib', '.a'],
    'com.apple.product-type.tool':              ['compiled.mach-o.executable',
                                                 '', ''],
    'com.apple.product-type.bundle.unit-test':  ['wrapper.cfbundle',
                                                 '', '.xctest'],
    'com.googlecode.gyp.xcode.bundle':          ['compiled.mach-o.dylib',
                                                 '', '.so'],
  }

  def __init__(self, properties=None, id=None, parent=None,
               force_outdir=None, force_prefix=None, force_extension=None):
    # super
    XCTarget.__init__(self, properties, id, parent)

    if 'productName' in self._properties and \
       'productType' in self._properties and \
       not 'productReference' in self._properties and \
       self._properties['productType'] in self._product_filetypes:
      products_group = None
      pbxproject = self.PBXProjectAncestor()
      if pbxproject != None:
        products_group = pbxproject.ProductsGroup()

      if products_group != None:
        (filetype, prefix, suffix) = \
            self._product_filetypes[self._properties['productType']]
        # Xcode does not have a distinct type for loadable modules that are
        # pure BSD targets (not in a bundle wrapper). GYP allows such modules
        # to be specified by setting a target type to loadable_module without
        # having mac_bundle set. These are mapped to the pseudo-product type
        # com.googlecode.gyp.xcode.bundle.
        #
        # By picking up this special type and converting it to a dynamic
        # library (com.apple.product-type.library.dynamic) with fix-ups,
        # single-file loadable modules can be produced.
        #
        # MACH_O_TYPE is changed to mh_bundle to produce the proper file type
        # (as opposed to mh_dylib). In order for linking to succeed,
        # DYLIB_CURRENT_VERSION and DYLIB_COMPATIBILITY_VERSION must be
        # cleared. They are meaningless for type mh_bundle.
        #
        # Finally, the .so extension is forcibly applied over the default
        # (.dylib), unless another forced extension is already selected.
        # .dylib is plainly wrong, and .bundle is used by loadable_modules in
        # bundle wrappers (com.apple.product-type.bundle). .so seems an odd
        # choice because it's used as the extension on many other systems that
        # don't distinguish between linkable shared libraries and non-linkable
        # loadable modules, but there's precedent: Python loadable modules on
        # Mac OS X use an .so extension.
        if self._properties['productType'] == 'com.googlecode.gyp.xcode.bundle':
          self._properties['productType'] = \
              'com.apple.product-type.library.dynamic'
          self.SetBuildSetting('MACH_O_TYPE', 'mh_bundle')
          self.SetBuildSetting('DYLIB_CURRENT_VERSION', '')
          self.SetBuildSetting('DYLIB_COMPATIBILITY_VERSION', '')
          if force_extension is None:
            force_extension = suffix[1:]

        if self._properties['productType'] == \
           'com.apple.product-type-bundle.unit.test':
          if force_extension is None:
            force_extension = suffix[1:]

        if force_extension is not None:
          # If it's a wrapper (bundle), set WRAPPER_EXTENSION.
          # Extension override.
          suffix = '.' + force_extension
          if filetype.startswith('wrapper.'):
            self.SetBuildSetting('WRAPPER_EXTENSION', force_extension)
          else:
            self.SetBuildSetting('EXECUTABLE_EXTENSION', force_extension)

          if filetype.startswith('compiled.mach-o.executable'):
            product_name = self._properties['productName']
            product_name += suffix
            suffix = ''
            self.SetProperty('productName', product_name)
            self.SetBuildSetting('PRODUCT_NAME', product_name)

        # Xcode handles most prefixes based on the target type, however there
        # are exceptions.  If a "BSD Dynamic Library" target is added in the
        # Xcode UI, Xcode sets EXECUTABLE_PREFIX.  This check duplicates that
        # behavior.
        if force_prefix is not None:
          prefix = force_prefix
        if filetype.startswith('wrapper.'):
          self.SetBuildSetting('WRAPPER_PREFIX', prefix)
        else:
          self.SetBuildSetting('EXECUTABLE_PREFIX', prefix)

        if force_outdir is not None:
          self.SetBuildSetting('TARGET_BUILD_DIR', force_outdir)

        # TODO(tvl): Remove the below hack.
        #    http://code.google.com/p/gyp/issues/detail?id=122

        # Some targets include the prefix in the target_name.  These targets
        # really should just add a product_name setting that doesn't include
        # the prefix.  For example:
        #  target_name = 'libevent', product_name = 'event'
        # This check cleans up for them.
        product_name = self._properties['productName']
        prefix_len = len(prefix)
        if prefix_len and (product_name[:prefix_len] == prefix):
          product_name = product_name[prefix_len:]
          self.SetProperty('productName', product_name)
          self.SetBuildSetting('PRODUCT_NAME', product_name)

        ref_props = {
          'explicitFileType': filetype,
          'includeInIndex':   0,
          'path':             prefix + product_name + suffix,
          'sourceTree':       'BUILT_PRODUCTS_DIR',
        }
        file_ref = PBXFileReference(ref_props)
        products_group.AppendChild(file_ref)
        self.SetProperty('productReference', file_ref)

  def GetBuildPhaseByType(self, type):
    if not 'buildPhases' in self._properties:
      return None

    the_phase = None
    for phase in self._properties['buildPhases']:
      if isinstance(phase, type):
        # Some phases may be present in multiples in a well-formed project file,
        # but phases like PBXSourcesBuildPhase may only be present singly, and
        # this function is intended as an aid to GetBuildPhaseByType.  Loop
        # over the entire list of phases and assert if more than one of the
        # desired type is found.
        assert the_phase is None
        the_phase = phase

    return the_phase

  def HeadersPhase(self):
    headers_phase = self.GetBuildPhaseByType(PBXHeadersBuildPhase)
    if headers_phase is None:
      headers_phase = PBXHeadersBuildPhase()

      # The headers phase should come before the resources, sources, and
      # frameworks phases, if any.
      insert_at = len(self._properties['buildPhases'])
      for index in xrange(0, len(self._properties['buildPhases'])):
        phase = self._properties['buildPhases'][index]
        if isinstance(phase, PBXResourcesBuildPhase) or \
           isinstance(phase, PBXSourcesBuildPhase) or \
           isinstance(phase, PBXFrameworksBuildPhase):
          insert_at = index
          break

      self._properties['buildPhases'].insert(insert_at, headers_phase)
      headers_phase.parent = self

    return headers_phase

  def ResourcesPhase(self):
    resources_phase = self.GetBuildPhaseByType(PBXResourcesBuildPhase)
    if resources_phase is None:
      resources_phase = PBXResourcesBuildPhase()

      # The resources phase should come before the sources and frameworks
      # phases, if any.
      insert_at = len(self._properties['buildPhases'])
      for index in xrange(0, len(self._properties['buildPhases'])):
        phase = self._properties['buildPhases'][index]
        if isinstance(phase, PBXSourcesBuildPhase) or \
           isinstance(phase, PBXFrameworksBuildPhase):
          insert_at = index
          break

      self._properties['buildPhases'].insert(insert_at, resources_phase)
      resources_phase.parent = self

    return resources_phase

  def SourcesPhase(self):
    sources_phase = self.GetBuildPhaseByType(PBXSourcesBuildPhase)
    if sources_phase is None:
      sources_phase = PBXSourcesBuildPhase()
      self.AppendProperty('buildPhases', sources_phase)

    return sources_phase

  def FrameworksPhase(self):
    frameworks_phase = self.GetBuildPhaseByType(PBXFrameworksBuildPhase)
    if frameworks_phase is None:
      frameworks_phase = PBXFrameworksBuildPhase()
      self.AppendProperty('buildPhases', frameworks_phase)

    return frameworks_phase

  def AddDependency(self, other):
    # super
    XCTarget.AddDependency(self, other)

    static_library_type = 'com.apple.product-type.library.static'
    shared_library_type = 'com.apple.product-type.library.dynamic'
    framework_type = 'com.apple.product-type.framework'
    if isinstance(other, PBXNativeTarget) and \
       'productType' in self._properties and \
       self._properties['productType'] != static_library_type and \
       'productType' in other._properties and \
       (other._properties['productType'] == static_library_type or \
        ((other._properties['productType'] == shared_library_type or \
          other._properties['productType'] == framework_type) and \
         ((not other.HasBuildSetting('MACH_O_TYPE')) or
          other.GetBuildSetting('MACH_O_TYPE') != 'mh_bundle'))):

      file_ref = other.GetProperty('productReference')

      pbxproject = self.PBXProjectAncestor()
      other_pbxproject = other.PBXProjectAncestor()
      if pbxproject != other_pbxproject:
        other_project_product_group = \
            pbxproject.AddOrGetProjectReference(other_pbxproject)[0]
        file_ref = other_project_product_group.GetChildByRemoteObject(file_ref)

      self.FrameworksPhase().AppendProperty('files',
                                            PBXBuildFile({'fileRef': file_ref}))


class PBXAggregateTarget(XCTarget):
  pass


class PBXProject(XCContainerPortal):
  # A PBXProject is really just an XCObject, the XCContainerPortal thing is
  # just to allow PBXProject to be used in the containerPortal property of
  # PBXContainerItemProxy.
  """

  Attributes:
    path: "sample.xcodeproj".  TODO(mark) Document me!
    _other_pbxprojects: A dictionary, keyed by other PBXProject objects.  Each
                        value is a reference to the dict in the
                        projectReferences list associated with the keyed
                        PBXProject.
  """

  _schema = XCContainerPortal._schema.copy()
  _schema.update({
    'attributes':             [0, dict,                0, 0],
    'buildConfigurationList': [0, XCConfigurationList, 1, 1,
                               XCConfigurationList()],
    'compatibilityVersion':   [0, str,                 0, 1, 'Xcode 3.2'],
    'hasScannedForEncodings': [0, int,                 0, 1, 1],
    'mainGroup':              [0, PBXGroup,            1, 1, PBXGroup()],
    'projectDirPath':         [0, str,                 0, 1, ''],
    'projectReferences':      [1, dict,                0, 0],
    'projectRoot':            [0, str,                 0, 1, ''],
    'targets':                [1, XCTarget,            1, 1, []],
  })

  def __init__(self, properties=None, id=None, parent=None, path=None):
    self.path = path
    self._other_pbxprojects = {}
    # super
    return XCContainerPortal.__init__(self, properties, id, parent)

  def Name(self):
    name = self.path
    if name[-10:] == '.xcodeproj':
      name = name[:-10]
    return posixpath.basename(name)

  def Path(self):
    return self.path

  def Comment(self):
    return 'Project object'

  def Children(self):
    # super
    children = XCContainerPortal.Children(self)

    # Add children that the schema doesn't know about.  Maybe there's a more
    # elegant way around this, but this is the only case where we need to own
    # objects in a dictionary (that is itself in a list), and three lines for
    # a one-off isn't that big a deal.
    if 'projectReferences' in self._properties:
      for reference in self._properties['projectReferences']:
        children.append(reference['ProductGroup'])

    return children

  def PBXProjectAncestor(self):
    return self

  def _GroupByName(self, name):
    if not 'mainGroup' in self._properties:
      self.SetProperty('mainGroup', PBXGroup())

    main_group = self._properties['mainGroup']
    group = main_group.GetChildByName(name)
    if group is None:
      group = PBXGroup({'name': name})
      main_group.AppendChild(group)

    return group

  # SourceGroup and ProductsGroup are created by default in Xcode's own
  # templates.
  def SourceGroup(self):
    return self._GroupByName('Source')

  def ProductsGroup(self):
    return self._GroupByName('Products')

  # IntermediatesGroup is used to collect source-like files that are generated
  # by rules or script phases and are placed in intermediate directories such
  # as DerivedSources.
  def IntermediatesGroup(self):
    return self._GroupByName('Intermediates')

  # FrameworksGroup and ProjectsGroup are top-level groups used to collect
  # frameworks and projects.
  def FrameworksGroup(self):
    return self._GroupByName('Frameworks')

  def ProjectsGroup(self):
    return self._GroupByName('Projects')

  def RootGroupForPath(self, path):
    """Returns a PBXGroup child of this object to which path should be added.

    This method is intended to choose between SourceGroup and
    IntermediatesGroup on the basis of whether path is present in a source
    directory or an intermediates directory.  For the purposes of this
    determination, any path located within a derived file directory such as
    PROJECT_DERIVED_FILE_DIR is treated as being in an intermediates
    directory.

    The returned value is a two-element tuple.  The first element is the
    PBXGroup, and the second element specifies whether that group should be
    organized hierarchically (True) or as a single flat list (False).
    """

    # TODO(mark): make this a class variable and bind to self on call?
    # Also, this list is nowhere near exhaustive.
    # INTERMEDIATE_DIR and SHARED_INTERMEDIATE_DIR are used by
    # gyp.generator.xcode.  There should probably be some way for that module
    # to push the names in, rather than having to hard-code them here.
    source_tree_groups = {
      'DERIVED_FILE_DIR':         (self.IntermediatesGroup, True),
      'INTERMEDIATE_DIR':         (self.IntermediatesGroup, True),
      'PROJECT_DERIVED_FILE_DIR': (self.IntermediatesGroup, True),
      'SHARED_INTERMEDIATE_DIR':  (self.IntermediatesGroup, True),
    }

    (source_tree, path) = SourceTreeAndPathFromPath(path)
    if source_tree != None and source_tree in source_tree_groups:
      (group_func, hierarchical) = source_tree_groups[source_tree]
      group = group_func()
      return (group, hierarchical)

    # TODO(mark): make additional choices based on file extension.

    return (self.SourceGroup(), True)

  def AddOrGetFileInRootGroup(self, path):
    """Returns a PBXFileReference corresponding to path in the correct group
    according to RootGroupForPath's heuristics.

    If an existing PBXFileReference for path exists, it will be returned.
    Otherwise, one will be created and returned.
    """

    (group, hierarchical) = self.RootGroupForPath(path)
    return group.AddOrGetFileByPath(path, hierarchical)

  def RootGroupsTakeOverOnlyChildren(self, recurse=False):
    """Calls TakeOverOnlyChild for all groups in the main group."""

    for group in self._properties['mainGroup']._properties['children']:
      if isinstance(group, PBXGroup):
        group.TakeOverOnlyChild(recurse)

  def SortGroups(self):
    # Sort the children of the mainGroup (like "Source" and "Products")
    # according to their defined order.
    self._properties['mainGroup']._properties['children'] = \
        sorted(self._properties['mainGroup']._properties['children'],
               cmp=lambda x,y: x.CompareRootGroup(y))

    # Sort everything else by putting group before files, and going
    # alphabetically by name within sections of groups and files.  SortGroup
    # is recursive.
    for group in self._properties['mainGroup']._properties['children']:
      if not isinstance(group, PBXGroup):
        continue

      if group.Name() == 'Products':
        # The Products group is a special case.  Instead of sorting
        # alphabetically, sort things in the order of the targets that
        # produce the products.  To do this, just build up a new list of
        # products based on the targets.
        products = []
        for target in self._properties['targets']:
          if not isinstance(target, PBXNativeTarget):
            continue
          product = target._properties['productReference']
          # Make sure that the product is already in the products group.
          assert product in group._properties['children']
          products.append(product)

        # Make sure that this process doesn't miss anything that was already
        # in the products group.
        assert len(products) == len(group._properties['children'])
        group._properties['children'] = products
      else:
        group.SortGroup()

  def AddOrGetProjectReference(self, other_pbxproject):
    """Add a reference to another project file (via PBXProject object) to this
    one.

    Returns [ProductGroup, ProjectRef].  ProductGroup is a PBXGroup object in
    this project file that contains a PBXReferenceProxy object for each
    product of each PBXNativeTarget in the other project file.  ProjectRef is
    a PBXFileReference to the other project file.

    If this project file already references the other project file, the
    existing ProductGroup and ProjectRef are returned.  The ProductGroup will
    still be updated if necessary.
    """

    if not 'projectReferences' in self._properties:
      self._properties['projectReferences'] = []

    product_group = None
    project_ref = None

    if not other_pbxproject in self._other_pbxprojects:
      # This project file isn't yet linked to the other one.  Establish the
      # link.
      product_group = PBXGroup({'name': 'Products'})

      # ProductGroup is strong.
      product_group.parent = self

      # There's nothing unique about this PBXGroup, and if left alone, it will
      # wind up with the same set of hashables as all other PBXGroup objects
      # owned by the projectReferences list.  Add the hashables of the
      # remote PBXProject that it's related to.
      product_group._hashables.extend(other_pbxproject.Hashables())

      # The other project reports its path as relative to the same directory
      # that this project's path is relative to.  The other project's path
      # is not necessarily already relative to this project.  Figure out the
      # pathname that this project needs to use to refer to the other one.
      this_path = posixpath.dirname(self.Path())
      projectDirPath = self.GetProperty('projectDirPath')
      if projectDirPath:
        if posixpath.isabs(projectDirPath[0]):
          this_path = projectDirPath
        else:
          this_path = posixpath.join(this_path, projectDirPath)
      other_path = gyp.common.RelativePath(other_pbxproject.Path(), this_path)

      # ProjectRef is weak (it's owned by the mainGroup hierarchy).
      project_ref = PBXFileReference({
            'lastKnownFileType': 'wrapper.pb-project',
            'path':              other_path,
            'sourceTree':        'SOURCE_ROOT',
          })
      self.ProjectsGroup().AppendChild(project_ref)

      ref_dict = {'ProductGroup': product_group, 'ProjectRef': project_ref}
      self._other_pbxprojects[other_pbxproject] = ref_dict
      self.AppendProperty('projectReferences', ref_dict)

      # Xcode seems to sort this list case-insensitively
      self._properties['projectReferences'] = \
          sorted(self._properties['projectReferences'], cmp=lambda x,y:
                 cmp(x['ProjectRef'].Name().lower(),
                     y['ProjectRef'].Name().lower()))
    else:
      # The link already exists.  Pull out the relevnt data.
      project_ref_dict = self._other_pbxprojects[other_pbxproject]
      product_group = project_ref_dict['ProductGroup']
      project_ref = project_ref_dict['ProjectRef']

    self._SetUpProductReferences(other_pbxproject, product_group, project_ref)

    return [product_group, project_ref]

  def _SetUpProductReferences(self, other_pbxproject, product_group,
                              project_ref):
    # TODO(mark): This only adds references to products in other_pbxproject
    # when they don't exist in this pbxproject.  Perhaps it should also
    # remove references from this pbxproject that are no longer present in
    # other_pbxproject.  Perhaps it should update various properties if they
    # change.
    for target in other_pbxproject._properties['targets']:
      if not isinstance(target, PBXNativeTarget):
        continue

      other_fileref = target._properties['productReference']
      if product_group.GetChildByRemoteObject(other_fileref) is None:
        # Xcode sets remoteInfo to the name of the target and not the name
        # of its product, despite this proxy being a reference to the product.
        container_item = PBXContainerItemProxy({
              'containerPortal':      project_ref,
              'proxyType':            2,
              'remoteGlobalIDString': other_fileref,
              'remoteInfo':           target.Name()
            })
        # TODO(mark): Does sourceTree get copied straight over from the other
        # project?  Can the other project ever have lastKnownFileType here
        # instead of explicitFileType?  (Use it if so?)  Can path ever be
        # unset?  (I don't think so.)  Can other_fileref have name set, and
        # does it impact the PBXReferenceProxy if so?  These are the questions
        # that perhaps will be answered one day.
        reference_proxy = PBXReferenceProxy({
              'fileType':   other_fileref._properties['explicitFileType'],
              'path':       other_fileref._properties['path'],
              'sourceTree': other_fileref._properties['sourceTree'],
              'remoteRef':  container_item,
            })

        product_group.AppendChild(reference_proxy)

  def SortRemoteProductReferences(self):
    # For each remote project file, sort the associated ProductGroup in the
    # same order that the targets are sorted in the remote project file.  This
    # is the sort order used by Xcode.

    def CompareProducts(x, y, remote_products):
      # x and y are PBXReferenceProxy objects.  Go through their associated
      # PBXContainerItem to get the remote PBXFileReference, which will be
      # present in the remote_products list.
      x_remote = x._properties['remoteRef']._properties['remoteGlobalIDString']
      y_remote = y._properties['remoteRef']._properties['remoteGlobalIDString']
      x_index = remote_products.index(x_remote)
      y_index = remote_products.index(y_remote)

      # Use the order of each remote PBXFileReference in remote_products to
      # determine the sort order.
      return cmp(x_index, y_index)

    for other_pbxproject, ref_dict in self._other_pbxprojects.iteritems():
      # Build up a list of products in the remote project file, ordered the
      # same as the targets that produce them.
      remote_products = []
      for target in other_pbxproject._properties['targets']:
        if not isinstance(target, PBXNativeTarget):
          continue
        remote_products.append(target._properties['productReference'])

      # Sort the PBXReferenceProxy children according to the list of remote
      # products.
      product_group = ref_dict['ProductGroup']
      product_group._properties['children'] = sorted(
          product_group._properties['children'],
          cmp=lambda x, y: CompareProducts(x, y, remote_products))


class XCProjectFile(XCObject):
  _schema = XCObject._schema.copy()
  _schema.update({
    'archiveVersion': [0, int,        0, 1, 1],
    'classes':        [0, dict,       0, 1, {}],
    'objectVersion':  [0, int,        0, 1, 45],
    'rootObject':     [0, PBXProject, 1, 1],
  })

  def SetXcodeVersion(self, version):
    version_to_object_version = {
      '2.4': 45,
      '3.0': 45,
      '3.1': 45,
      '3.2': 46,
    }
    if not version in version_to_object_version:
      supported_str = ', '.join(sorted(version_to_object_version.keys()))
      raise Exception(
          'Unsupported Xcode version %s (supported: %s)' %
          ( version, supported_str ) )
    compatibility_version = 'Xcode %s' % version
    self._properties['rootObject'].SetProperty('compatibilityVersion',
                                               compatibility_version)
    self.SetProperty('objectVersion', version_to_object_version[version]);

  def ComputeIDs(self, recursive=True, overwrite=True, hash=None):
    # Although XCProjectFile is implemented here as an XCObject, it's not a
    # proper object in the Xcode sense, and it certainly doesn't have its own
    # ID.  Pass through an attempt to update IDs to the real root object.
    if recursive:
      self._properties['rootObject'].ComputeIDs(recursive, overwrite, hash)

  def Print(self, file=sys.stdout):
    self.VerifyHasRequiredProperties()

    # Add the special "objects" property, which will be caught and handled
    # separately during printing.  This structure allows a fairly standard
    # loop do the normal printing.
    self._properties['objects'] = {}
    self._XCPrint(file, 0, '// !$*UTF8*$!\n')
    if self._should_print_single_line:
      self._XCPrint(file, 0, '{ ')
    else:
      self._XCPrint(file, 0, '{\n')
    for property, value in sorted(self._properties.iteritems(),
                                  cmp=lambda x, y: cmp(x, y)):
      if property == 'objects':
        self._PrintObjects(file)
      else:
        self._XCKVPrint(file, 1, property, value)
    self._XCPrint(file, 0, '}\n')
    del self._properties['objects']

  def _PrintObjects(self, file):
    if self._should_print_single_line:
      self._XCPrint(file, 0, 'objects = {')
    else:
      self._XCPrint(file, 1, 'objects = {\n')

    objects_by_class = {}
    for object in self.Descendants():
      if object == self:
        continue
      class_name = object.__class__.__name__
      if not class_name in objects_by_class:
        objects_by_class[class_name] = []
      objects_by_class[class_name].append(object)

    for class_name in sorted(objects_by_class):
      self._XCPrint(file, 0, '\n')
      self._XCPrint(file, 0, '/* Begin ' + class_name + ' section */\n')
      for object in sorted(objects_by_class[class_name],
                           cmp=lambda x, y: cmp(x.id, y.id)):
        object.Print(file)
      self._XCPrint(file, 0, '/* End ' + class_name + ' section */\n')

    if self._should_print_single_line:
      self._XCPrint(file, 0, '}; ')
    else:
      self._XCPrint(file, 1, '};\n')
