# Copyright (c) 2011 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 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")
