"""Stamps a plugin xml with build information."""

import argparse
import re
from xml.dom.minidom import parse

parser = argparse.ArgumentParser()

parser.add_argument(
    "--plugin_xml",
    help="The plugin xml file",
    required=True,
)
parser.add_argument(
    "--api_version_txt",
    help="The file containing the api version info",
    required=True,
)
parser.add_argument(
    "--stamp_since_build",
    action="store_true",
    help="Stamp since-build with the build number",
)
parser.add_argument(
    "--stamp_until_build",
    action="store_true",
    help="Stamp until-build with the build number",
)
parser.add_argument(
    "--plugin_id",
    help="plugin ID to stamp into the plugin.xml",
)
parser.add_argument(
    "--plugin_name",
    help="plugin name to stamp into the plugin.xml",
)
parser.add_argument(
    "--version_file",
    help="Version file to stamp into the plugin.xml",
)
parser.add_argument(
    "--changelog_file",
    help="Changelog file to add to plugin.xml",
)
parser.add_argument(
    "--description_file",
    help="File with description element data to add to plugin.xml",
)
parser.add_argument(
    "--vendor_file",
    help="File with vendor element data to add to plugin.xml",
)
parser.add_argument(
    "--include_product_code_in_stamp",
    action="store_true",
    help="Include the product code in the stamp",
)


def _read_changelog(changelog_file):
  """Reads the changelog and transforms it into trivial HTML."""
  with open(changelog_file) as f:
    return "\n".join("<p>" + line + "</p>" for line in f.readlines())


def _read_description(description_file):
  """Reads the description and transforms it into trivial HTML."""
  with open(description_file) as f:
    return "\n".join("<p>" + line + "</p>" for line in f.readlines())


def _read_vendor(vendor_file):
  """Reads vendor data from an .xml file and returns the vendor element."""
  dom = parse(vendor_file)
  vendor_elements = dom.getElementsByTagName("vendor")
  if len(vendor_elements) != 1:
    raise ValueError("Ambigious or missing vendor element (%d elements)" %
                     len(vendor_elements))
  return vendor_elements[0]


def _strip_product_code(api_version):
  """Strips the product code from the api version string."""
  match = re.match(r"^([A-Z]+-)?([0-9]+)((\.[0-9]+)*)", api_version)
  if match is None:
    raise ValueError("Invalid build number: " + api_version)

  return match.group(2) + match.group(3)


def main():
  args = parser.parse_args()

  dom = parse(args.plugin_xml)

  with open(args.api_version_txt) as f:
    api_version = f.readline().strip()

  new_elements = []

  idea_plugin = dom.documentElement

  version_element = None
  version_elements = idea_plugin.getElementsByTagName("version")
  if len(version_elements) > 1:
    raise ValueError("Ambigious version element")

  if len(version_elements) == 1:
    version_element = version_elements[0].firstChild

  if args.version_file:
    if version_element:
      raise ValueError("version element already in plugin.xml")
    version_element = dom.createElement("version")
    new_elements.append(version_element)
    with open(args.version_file) as f:
      value = f.read().strip()
      version_text = dom.createTextNode(value)
      version_element.appendChild(version_text)

  if args.stamp_since_build or args.stamp_until_build:
    if idea_plugin.getElementsByTagName("idea-version"):
      raise ValueError("idea-version element already present")

    idea_version_build_element = (api_version
                                  if args.include_product_code_in_stamp else
                                  _strip_product_code(api_version))

    idea_version_element = dom.createElement("idea-version")
    new_elements.append(idea_version_element)

    if args.stamp_since_build:
      idea_version_element.setAttribute("since-build",
                                        idea_version_build_element)
    if args.stamp_until_build:
      idea_version_element.setAttribute("until-build",
                                        idea_version_build_element)

  if args.changelog_file:
    if idea_plugin.getElementsByTagName("change-notes"):
      raise ValueError("change-notes element already in plugin.xml")
    changelog_element = dom.createElement("change-notes")
    changelog_text = _read_changelog(args.changelog_file)
    changelog_cdata = dom.createCDATASection(changelog_text)
    changelog_element.appendChild(changelog_cdata)
    new_elements.append(changelog_element)

  if args.plugin_id:
    if idea_plugin.getElementsByTagName("id"):
      raise ValueError("id element already in plugin.xml")
    id_element = dom.createElement("id")
    new_elements.append(id_element)
    id_text = dom.createTextNode(args.plugin_id)
    id_element.appendChild(id_text)

  if args.plugin_name:
    if idea_plugin.getElementsByTagName("name"):
      raise ValueError("name element already in plugin.xml")
    name_element = dom.createElement("name")
    new_elements.append(name_element)
    name_text = dom.createTextNode(args.plugin_name)
    name_element.appendChild(name_text)

  if args.description_file:
    if idea_plugin.getElementsByTagName("description"):
      raise ValueError("description element already in plugin.xml")
    description_element = dom.createElement("description")
    description_text = _read_description(args.description_file)
    description_cdata = dom.createCDATASection(description_text)
    description_element.appendChild(description_cdata)
    new_elements.append(description_element)

  if args.vendor_file:
    if idea_plugin.getElementsByTagName("vendor"):
      raise ValueError("vendor element already in plugin.xml")
    vendor_element = dom.createElement("vendor")
    vendor_src_element = _read_vendor(args.vendor_file)
    vendor_element.setAttribute("email",
                                vendor_src_element.getAttribute("email"))
    vendor_element.setAttribute("url", vendor_src_element.getAttribute("url"))
    vendor_text = dom.createTextNode(vendor_src_element.firstChild.data)
    vendor_element.appendChild(vendor_text)
    new_elements.append(vendor_element)

  for new_element in new_elements:
    idea_plugin.appendChild(new_element)

  print dom.toxml()


if __name__ == "__main__":
  main()
