#!/usr/bin/env python3

import xml.etree.ElementTree as ET

projectID = 'VX999'
calFreq = 100
nStream = 26

# From stack overflow
#     https://stackoverflow.com/questions/28813876/how-do-i-get-pythons-elementtree-to-pretty-print-to-an-xml-file

def _pretty_print(current, parent=None, index=-1, depth=0):
    for i, node in enumerate(current):
        _pretty_print(node, current, i, depth + 1)
    if parent is not None:
        if index == 0:
            parent.text = '\n' + ('  ' * depth)
        else:
            parent[index - 1].tail = '\n' + ('  ' * depth)
        if index == len(parent) - 1:
            current.tail = '\n' + ('  ' * (depth - 1))

root = ET.Element("obs_cmd")

command = ET.SubElement(root, "command")
command.text = "configure"

beam_config = ET.SubElement(root, "beam_configuration")
ET.SubElement(beam_config, "nbeam", key="NBEAM").text = "1"
ET.SubElement(beam_config, "beam_state_0", key="BEAM_STATE_0", name="1").text = "1"

stream_config = ET.SubElement(root, "stream_configuration")
ET.SubElement(stream_config, "nstream", key="NSTREAM").text = str(nStream)
for i in range(nStream):
    ET.SubElement(stream_config, "active", key="STREAM_ACTIVE").text = "1"

source = ET.SubElement(root, "source_parameters")
ET.SubElement(source, "name", key="SOURCE", epoch="J2000").text = "VLBI"
ET.SubElement(source, "ra", key="RA", units="hh:mm:ss").text = "00:00:00"
ET.SubElement(source, "dec", key="DEC", units="dd:mm:ss").text = "00:00:00"

obs_parm = ET.SubElement(root, "observation_parameters")
ET.SubElement(obs_parm, "observer", key="OBSERVER").text = "VLBI"
ET.SubElement(obs_parm, "project_id", key="PID").text = projectID
ET.SubElement(obs_parm, "utc_start", key="UTC_START").text = "None"
ET.SubElement(obs_parm, "utc_stop", key="UTC_STOP").text = "None"

cal_parm = ET.SubElement(root, "calibration_parameters")
ET.SubElement(cal_parm, "signal", key="CAL_SIGNAL").text = "1"
ET.SubElement(cal_parm, "freq", key="CAL_FREQ", units="Hertz").text = str(calFreq)
ET.SubElement(cal_parm, "phase", key="CAL_PHASE").text = "0.0"
ET.SubElement(cal_parm, "duty_cycle", key="CAL_DUTY_CYCLE").text = "0.5"
ET.SubElement(cal_parm, "epoch", key="CAL_EPOCH", units="YYYY-DD-MM-HH:MM:SS+0").text = "ADDSOMETIME"
ET.SubElement(cal_parm, "tsys_avg_time", key="TSYS_AVG_TIME", units="seconds").text = "5"
ET.SubElement(cal_parm, "tsys_freq_resolution", key="TSYS_FREQ_RES", units="MHz").text = "1"

for i in range(nStream):
    stream = ET.SubElement(root, "stream{:d}".format(i))

    custom_param = ET.SubElement(stream, "custom_parameters")
    ET.SubElement(custom_param, "adaptive_filter", key="ADAPTIVE_FILTER").text = "0"
    ET.SubElement(custom_param, "adaptive_filter_epsilon", key="ADAPTIVE_FILTER_EPSILON").text = "0.1"
    ET.SubElement(custom_param, "adaptive_filter_nchan", key="ADAPTIVE_FILTER_NCHAN").text = "128"
    ET.SubElement(custom_param, "adaptive_filter_nsamp", key="ADAPTIVE_FILTER_NSAMP").text = "1024"
    ET.SubElement(custom_param, "schedule_block_id", key="SCHED_BLOCK_ID").text = "0"
    ET.SubElement(custom_param, "scan_id", key="SCAN_ID").text = "0"
    ET.SubElement(custom_param, "raw_baseband", key="RECORD_RAW_BASEBAND").text = "0"

    processing_modes = ET.SubElement(stream, "processing_modes")
    ET.SubElement(processing_modes, "fold", key="PERFORM_FOLD").text = "0"
    ET.SubElement(processing_modes, "search", key="PERFORM_SEARCH").text = "0"
    ET.SubElement(processing_modes, "continuum", key="PERFORM_CONTINUUM").text = "0"
    ET.SubElement(processing_modes, "spectral_line", key="PERFORM_SPECTRAL_LINE").text = "0"
    ET.SubElement(processing_modes, "vlbi", key="PERFORM_VLBI").text = "0"
    ET.SubElement(processing_modes, "baseband", key="PERFORM_BASEBAND").text = "0"

    zoom_proc_param = ET.SubElement(stream, "zoom_processing_parameters")
    ET.SubElement(zoom_proc_param, "active1", key="ZOOM1_ACTIVE").text = "0"
    ET.SubElement(zoom_proc_param, "bandwidth1", key="ZOOM1_BW", units="MHz").text = "4"
    ET.SubElement(zoom_proc_param, "frequency1", key="ZOOM1_FREQUENCY", units="MHz").text = "832"
    ET.SubElement(zoom_proc_param, "mode1", key="ZOOM1_MODE").text = "baseband"
    ET.SubElement(zoom_proc_param, "active2", key="ZOOM2_ACTIVE").text = "0"
    ET.SubElement(zoom_proc_param, "bandwidth2", key="ZOOM2_BW", units="MHz").text = "4"
    ET.SubElement(zoom_proc_param, "frequency2", key="ZOOM2_FREQUENCY", units="MHz").text = "832"
    ET.SubElement(zoom_proc_param, "mode2", key="ZOOM2_MODE").text = "baseband"

    vlbi_proc_param = ET.SubElement(stream, "vlbi_processing_parameters")
    ET.SubElement(vlbi_proc_param, "output_nbit", key="VLBI_OUTNBIT").text = "8"
    ET.SubElement(vlbi_proc_param, "output_encoding", key="VLBI_ENCODING").text = "offset_binary"
    ET.SubElement(vlbi_proc_param, "dest_ip", key="VLBI_DEST_IP").text = "10.17.10.1"
    ET.SubElement(vlbi_proc_param, "dest_port", key="VLBI_DEST_PORT").text = "10000"
    ET.SubElement(vlbi_proc_param, "vdif_thread_id", key="VLBI_VDIF_THREAD_ID").text = "0"
    ET.SubElement(vlbi_proc_param, "dest_protocol", key="VLBI_DEST_PROTOCOL").text = "udp"
    ET.SubElement(vlbi_proc_param, "dest_sequence_number", key="VLBI_DEST_SEQ_NO").text = "1"

_pretty_print(root)
tree = ET.ElementTree(root)
tree.write("configure-test.xml", encoding="ISO-8859-1", xml_declaration = True)

