#!/usr/bin/env python3

import sys
import xml.etree.ElementTree as etree

passed = True

def check_result(check, message):
  global passed
  if check:
    print('passed')
  elif message:
    print('failed: ' + message)
    passed = False
  else:
    print('failed')
    passed = False

def all_descendants(wix, name):
  for e in wix.iter():
    if e.tag == '{http://schemas.microsoft.com/wix/2006/wi}' + name:
      yield e

def children(e, name):
  for c in e:
    if not isinstance(c, str):
      if c.tag == '{http://schemas.microsoft.com/wix/2006/wi}' + name:
        yield c

def element_map(wix, name):
  print('testing for duplicate \'' + name + '\' ids ... ', end='')
  items = {}
  duplicates = []
  for e in all_descendants(wix, name):
    id = e.attrib.get("Id")
    if id in items.keys():
      duplicates.append(id)
    else:
      items[id] = e
  check_result(len(duplicates) == 0 , ', '.join(duplicates))
  return items

def check_element_guids(wix, name):
  print('testing for duplicate \'' + name + '\' guids ... ', end='')
  guids = []
  missing_guids = []
  duplicates = []
  for e in all_descendants(wix, name):
    id = e.attrib.get("Id")
    guid = e.attrib.get("Guid")
    if not guid:
      missing_guids.append(id)
    elif guid in guids:
      duplicates.append(guid)
    else:
      guids.append(guid)
  check_result(len(duplicates) == 0 , ', '.join(duplicates))
  return (guids, missing_guids)

def check_references(nodes, node_name, name, item_name, items):
  print('testing for missing \'' + item_name + '\' ids in \'' + node_name + '/' + name + '\' ... ', end='')
  missing = []
  for node in nodes.values():
    for ref in children(node, name):
      id = ref.attrib.get("Id")
      if not id in items.keys():
        missing.append(id)
  check_result(len(missing) == 0 , ', '.join(missing))

# 1. Check for missing/duplicate ids ###################################################################################

wix = etree.parse('src/windows/installer/Product.wxs').getroot()
features = element_map(wix, 'Feature')
component_groups = element_map(wix, 'ComponentGroup')
components = element_map(wix, 'Component')
directories = element_map(wix, 'Directory')

check_references(features, 'Feature', 'ComponentGroupRef', 'ComponentGroup', component_groups)
check_references(component_groups, 'ComponentGroups', 'ComponentRef', 'Component', components)

# 2. Check for missing/duplicate guids #################################################################################

guids, missing_guids = check_element_guids(wix, 'Component')

print('testing for missing \'Component\' guids ... ', end='')
check_result(len(missing_guids) == 0 , ', '.join(missing_guids))

########################################################################################################################

if not passed:
  sys.exit(-1)
