######################################################################
# Copyright Trimble 2019
######################################################################
# Get info from config.xml

try:
  import xml.etree.cElementTree as ET
except ImportError:
  import xml.etree.ElementTree as ET

def find_opt_text(elem,tag_name):
  tag = elem.find(tag_name)
  if(tag != None):
    tag = tag.text
  return tag

def find_opt_obj(elem,tag_name):
  tag = elem.find(tag_name)
  return tag

# Using __slots__ lets pylint check for typos
class DeviceAg(object):
  '''Info from single receiver/device in config.xml'''
  __slots__ = ('skip_setup',
               'io_TSIP',
               'io_RTK_input',
               'io_NMEA_ZDA_output',
               'skip_install',
               'job_key',
               'build_name',
               'tnfs_ip')

  def __init__(self):
    pass
  def __repr__(self):
    mystr = '\n    '
    mystr += '\n    '.join("%s: %s" % (item,getattr(self,item,None)) for item in self.__slots__)
    return mystr

# Using __slots__ lets pylint check for typos
class Device(object):
  '''Info from single receiver/device in config.xml'''
  __slots__ = ('n',
               'ip',
               'desc',
               'long_desc',
               'build',
               'colossal_build',
               'disable_build_run',
               'user',
               'pw',
               'settingsClone',
               'patchFile',
               'useTerrasatBuild',
               'linux',
               'StingerAPI',
               'tag',
               'frozen',
               'do_RTK',
               'do_IMU',
               'imu_preference',
               'ag')
  def __init__(self):
    pass
  def __repr__(self):
    mystr = 'Device:\n  '
    mystr += '\n  '.join("%s: %s" % (item,getattr(self,item,None)) for item in self.__slots__)
    mystr += '\n'
    return mystr

# Using __slots__ lets pylint check for typos
class ConfigXml(object):
  '''All info from config.xml (+ a little global config info)'''
  __slots__ = ('disable_regression',
               'current_config_device', # It will be set to None if download_files_at_end_of_test() exits successfully, otherwise it is the problematic device to be removed.
               'detailedDiagCmd',
               'removed_devices',
               'jam_ref_rcvr',
               'jam_RF_control',
               'SampleConfig',
               'ScriptRoot',
               'ResultsQueue',
               'clean_builds',
               'allow_builds',
               'email_recipients',
               'email_host',
               'TNFS_server_root',
               'TNFS_server_ip_address',
               'spirent_IP',
               'spirent_password',
               'spirent_username',
               'spirent_serial',
               'spirent_transfer_speeds',
               'spirent_playback_drive',
               'spirent_ping_dirs',
               'allow_firmware_install',
               'devices',
               'GlobalRunNum')
  def __init__(self):
    self.clean_builds = True # delete Build directory before each test?  Otherwise just cvs update
    self.allow_builds = True # only set False for debugging!
    self.allow_firmware_install = True # upgrade FW?  Only set False for testing!
    self.current_config_device = None
    self.removed_devices = []
  def __repr__(self):
    mystr = 'ConfigXml:\n  '
    mystr += '\n  '.join("%s: %s" % (item,getattr(self,item,None)) for item in self.__slots__)
    mystr += '\n'
    return mystr

def get_config_xml(st, disable_regression):
  """Input: disable_regression = if True, the script will not touch any receivers.
  Return info from global config - mainly config.xml"""
  cfg = ConfigXml()
  tree = ET.ElementTree(file='config.xml')
  root = tree.getroot()
  cfg.disable_regression = disable_regression
  cfg.SampleConfig = root.find('SampleConfig').text
  cfg.ResultsQueue = root.find('ResultsQueue').text
  cfg.ScriptRoot = root.find('ScriptRoot').text

  cfg.jam_ref_rcvr = None
  cfg.jam_RF_control = None
  if root.find('jam') is not None:
    cfg.jam_ref_rcvr = root.find('jam/ref_rcvr').text
    cfg.jam_RF_control = root.find('jam/RF_control').text

  cfg.email_host = find_opt_text( root, 'NotifyOnError/emailHost' )

  cfg.email_recipients = []
  for elem in tree.iter(tag='emailErr'):
    cfg.email_recipients.append( elem.text )

  cfg.TNFS_server_root = find_opt_text(root, 'TNFS/TNFS_server_root')
  cfg.TNFS_server_ip_address = find_opt_text(root, 'TNFS/TNFS_server_ip_address')

  cfg.detailedDiagCmd = find_opt_text( root, 'detailed_diag_cmd' )

  cfg.spirent_IP = root.find('Spirent/IP').text
  cfg.spirent_username = root.find('Spirent/username').text
  cfg.spirent_password = root.find('Spirent/password').text
  cfg.spirent_serial = find_opt_text(root, 'Spirent/serial')
  cfg.spirent_transfer_speeds = {}
  cfg.spirent_transfer_speeds['network'] = float(root.find('Spirent/network_bytes_per_sec').text)
  cfg.spirent_playback_drive = None
  for elem in tree.iter(tag='usb_dir'):
    path = elem.find('path').text
    bytes_per_sec = elem.find('bytes_per_sec').text
    if elem.find('playback_drive') is not None:
      cfg.spirent_playback_drive = path
    cfg.spirent_transfer_speeds[path] = float(bytes_per_sec)
  cfg.spirent_ping_dirs = []
  for elem in tree.iter(tag='ping_dir'):
    cfg.spirent_ping_dirs.append( elem.text )

  cfg.devices = []

  # Now get details about the devices we are going to test
  for elem in tree.iter(tag='rx'):
    dev = Device()
    dev.n = int(elem.find('n').text)
    dev.ip = elem.find('ip').text
    dev.desc = elem.find('desc').text
    dev.long_desc = elem.find('long_desc').text
    dev.build = elem.find('build').text
    dev.linux = find_opt_text(elem, 'linux')
    dev.colossal_build = find_opt_text(elem,'colossal_build')
    dev.disable_build_run = find_opt_text(elem,'disable_build_run')
    dev.user = elem.find('user').text
    dev.pw = elem.find('pw').text
    dev.settingsClone = find_opt_text(elem,'settingsClone')
    dev.patchFile = find_opt_text(elem,'patchFile')
    dev.useTerrasatBuild = find_opt_text(elem,'useTerrasatBuild')
    dev.StingerAPI = find_opt_text(elem,'StingerAPI')
    dev.tag = find_opt_text(elem,'tag') # CVS tag
    dev.frozen = find_opt_text(elem,'frozen') # frozen date?
    dev.do_RTK = find_opt_text(elem,'do_RTK')
    dev.do_IMU = find_opt_text(elem,'do_IMU')
    dev.ag = find_opt_obj(elem,'ag')
    dev.imu_preference = find_opt_text(elem, 'imu_preference')
    for elem in elem.iter(tag='ag'):
      devAg = DeviceAg()
      devAg.skip_setup = find_opt_text(elem,'skip_setup')
      devAg.io_TSIP = find_opt_text(elem,'io_TSIP')
      devAg.io_RTK_input = find_opt_text(elem,'io_RTK_input')
      devAg.io_NMEA_ZDA_output = find_opt_text(elem,'io_NMEA_ZDA_output')
      devAg.skip_install = find_opt_text(elem,'skip_install')
      devAg.job_key = find_opt_text(elem,'job_key')
      devAg.build_name = find_opt_text(elem,'build_name')
      devAg.tnfs_ip = find_opt_text(elem,'tnfs_ip')
      dev.ag = devAg

    cfg.devices.append(dev)
    if not cfg.disable_regression and st is not None:
      st.loginfo.print_(dev)

  # Now load the current run number
  if cfg.disable_regression:
    cfg.GlobalRunNum = None
  else:
    fid = open('RunNum.txt','r')
    cfg.GlobalRunNum = int(fid.readline())
    fid.close()

  return cfg
