# 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.

"""Visual Studio project reader/writer."""

import gyp.common
import gyp.easy_xml as easy_xml

#------------------------------------------------------------------------------


class Tool(object):
  """Visual Studio tool."""

  def __init__(self, name, attrs=None):
    """Initializes the tool.

    Args:
      name: Tool name.
      attrs: Dict of tool attributes; may be None.
    """
    self._attrs = attrs or {}
    self._attrs['Name'] = name

  def _GetSpecification(self):
    """Creates an element for the tool.

    Returns:
      A new xml.dom.Element for the tool.
    """
    return ['Tool', self._attrs]

class Filter(object):
  """Visual Studio filter - that is, a virtual folder."""

  def __init__(self, name, contents=None):
    """Initializes the folder.

    Args:
      name: Filter (folder) name.
      contents: List of filenames and/or Filter objects contained.
    """
    self.name = name
    self.contents = list(contents or [])


#------------------------------------------------------------------------------


class Writer(object):
  """Visual Studio XML project writer."""

  def __init__(self, project_path, version, name, guid=None, platforms=None):
    """Initializes the project.

    Args:
      project_path: Path to the project file.
      version: Format version to emit.
      name: Name of the project.
      guid: GUID to use for project, if not None.
      platforms: Array of string, the supported platforms.  If null, ['Win32']
    """
    self.project_path = project_path
    self.version = version
    self.name = name
    self.guid = guid

    # Default to Win32 for platforms.
    if not platforms:
      platforms = ['Win32']

    # Initialize the specifications of the various sections.
    self.platform_section = ['Platforms']
    for platform in platforms:
      self.platform_section.append(['Platform', {'Name': platform}])
    self.tool_files_section = ['ToolFiles']
    self.configurations_section = ['Configurations']
    self.files_section = ['Files']

    # Keep a dict keyed on filename to speed up access.
    self.files_dict = dict()

  def AddToolFile(self, path):
    """Adds a tool file to the project.

    Args:
      path: Relative path from project to tool file.
    """
    self.tool_files_section.append(['ToolFile', {'RelativePath': path}])

  def _GetSpecForConfiguration(self, config_type, config_name, attrs, tools):
    """Returns the specification for a configuration.

    Args:
      config_type: Type of configuration node.
      config_name: Configuration name.
      attrs: Dict of configuration attributes; may be None.
      tools: List of tools (strings or Tool objects); may be None.
    Returns:
    """
    # Handle defaults
    if not attrs:
      attrs = {}
    if not tools:
      tools = []

    # Add configuration node and its attributes
    node_attrs = attrs.copy()
    node_attrs['Name'] = config_name
    specification = [config_type, node_attrs]

    # Add tool nodes and their attributes
    if tools:
      for t in tools:
        if isinstance(t, Tool):
          specification.append(t._GetSpecification())
        else:
          specification.append(Tool(t)._GetSpecification())
    return specification


  def AddConfig(self, name, attrs=None, tools=None):
    """Adds a configuration to the project.

    Args:
      name: Configuration name.
      attrs: Dict of configuration attributes; may be None.
      tools: List of tools (strings or Tool objects); may be None.
    """
    spec = self._GetSpecForConfiguration('Configuration', name, attrs, tools)
    self.configurations_section.append(spec)

  def _AddFilesToNode(self, parent, files):
    """Adds files and/or filters to the parent node.

    Args:
      parent: Destination node
      files: A list of Filter objects and/or relative paths to files.

    Will call itself recursively, if the files list contains Filter objects.
    """
    for f in files:
      if isinstance(f, Filter):
        node = ['Filter', {'Name': f.name}]
        self._AddFilesToNode(node, f.contents)
      else:
        node = ['File', {'RelativePath': f}]
        self.files_dict[f] = node
      parent.append(node)

  def AddFiles(self, files):
    """Adds files to the project.

    Args:
      files: A list of Filter objects and/or relative paths to files.

    This makes a copy of the file/filter tree at the time of this call.  If you
    later add files to a Filter object which was passed into a previous call
    to AddFiles(), it will not be reflected in this project.
    """
    self._AddFilesToNode(self.files_section, files)
    # TODO(rspangler) This also doesn't handle adding files to an existing
    # filter.  That is, it doesn't merge the trees.

  def AddFileConfig(self, path, config, attrs=None, tools=None):
    """Adds a configuration to a file.

    Args:
      path: Relative path to the file.
      config: Name of configuration to add.
      attrs: Dict of configuration attributes; may be None.
      tools: List of tools (strings or Tool objects); may be None.

    Raises:
      ValueError: Relative path does not match any file added via AddFiles().
    """
    # Find the file node with the right relative path
    parent = self.files_dict.get(path)
    if not parent:
      raise ValueError('AddFileConfig: file "%s" not in project.' % path)

    # Add the config to the file node
    spec = self._GetSpecForConfiguration('FileConfiguration', config, attrs,
                                         tools)
    parent.append(spec)

  def WriteIfChanged(self):
    """Writes the project file."""
    # First create XML content definition
    content = [
        'VisualStudioProject',
        {'ProjectType': 'Visual C++',
         'Version': self.version.ProjectVersion(),
         'Name': self.name,
         'ProjectGUID': self.guid,
         'RootNamespace': self.name,
         'Keyword': 'Win32Proj'
        },
        self.platform_section,
        self.tool_files_section,
        self.configurations_section,
        ['References'],  # empty section
        self.files_section,
        ['Globals']  # empty section
    ]
    easy_xml.WriteXmlIfChanged(content, self.project_path,
                               encoding="Windows-1252")
