from dis import pretty_flags

from PySide6 import QtWidgets  # Импорт модуля QtWidgets из библиотеки PySide6
from PySide6.QtGui import QPixmap,QFont
import sys  # Импорт модуля sys для работы с системными параметрами и выходом из программы
import numpy as np
import struct
import xml.etree.ElementTree as ET
from xml.dom import minidom


def switch(metric):
    if metric == 'nS':
        return 10**-9
    elif metric == 'uS':
        return 10**-6
    elif metric == 'mS':
        return 10**-3
    elif metric == 'S':
        return 1

def set_params():
    pulse_period_metric = pulse_period_combo_box.currentText()
    pulse_period = (np.int32(pulse_period_line_edit.text())) * switch(pulse_period_metric)

    pulse_width_metric = pulse_width_combo_box.currentText()
    pulse_width = (np.int32(pulse_width_line_edit.text())) * switch(pulse_width_metric)

    delay1_metric = delay1_combo_box.currentText()
    delay1 = (np.int32(delay1_line_edit.text())) * switch(delay1_metric)

    delay2_metric = delay2_combo_box.currentText()
    delay2 = (np.int32(delay2_line_edit.text())) * switch(delay2_metric)

    sample_freq = np.int32(sample_rate_box.currentText())
    pulse_number = np.int32(period_number_line_edit.text())
    print(f""" Pulse parameters:
          pulse width - {pulse_width} S
          pulse period - {pulse_period} S 
          delay 1 - {delay1} S
          delay 2 - {delay2} S
          pulse_number - {pulse_number}
          sample frequency {sample_freq} MHz""")
    #add = (pulse_width * pulse_number * sample_freq * (10**6) * 2)
    counter = 0
    n_high = round(pulse_width * sample_freq * (10 ** 6))
    print(f"high samples {n_high}")
    n_low = round((pulse_period - pulse_width) * sample_freq * (10 ** 6))
    print(f"low samples {n_low}")
    size_1 =(n_low + n_high) * 2
    print(f'rf array size_1 = {size_1}')

    size_2 = np.int32(size_1) * np.int32(pulse_number)
    print(f'rf array size_2 = {size_2}')
    rf_array = np.zeros(size_2, dtype=np.int8)

    for _ in range(0, pulse_number, 1):

        for _ in range(0, n_high, 1):

            rf_array[counter] = np.int8(127)
            rf_array[counter + 1] = np.int8(0)
            counter += 2
        for _ in range(0, n_low, 1):
            rf_array[counter] = np.int8(0)
            rf_array[counter + 1] = np.int8(0)
            counter += 2
    print(rf_array)

    f = open(f'pulse_pw_{pulse_width}_S_period_{pulse_period}_S_reps_{pulse_number}_delay1_{delay1}_delay2_{delay2}.bin', 'wb')  # открываем файл на чтение
#    f = open(f'test_100_pulses_10Msps_1ms.bin', 'wb')  # открываем файл на чтение

    for elem in rf_array:  # берём каждую строчку из файла f
        f.write(struct.pack('<b',elem))
    f.close()
    # write sync params in XML file

    root = ET.Element('root')


    rf = ET.SubElement(root, 'RF')
    sw = ET.SubElement(root, 'SW')
    adc = ET.SubElement(root, 'ADC')
    gru1 = ET.SubElement(root, 'GR')

    first_pulse_delay = 17 * 10 ** -6

    cl = ET.SubElement(root, 'CL')
    ET.SubElement(rf,'RF1').text = '0'
    ET.SubElement(sw,'SW1').text = '0'
    ET.SubElement(adc,'ADC1').text = '0'
    ET.SubElement(gru1,'GR1').text = '1'

    ET.SubElement(cl, 'CL1').text = str(round(first_pulse_delay/ (20*(10**-9))))

    param_count = 1

    delay1_cycles = round(delay1 / (20*(10**-9)))
    pw_cycles = round(pulse_width / (20*(10**-9)))
    low_cycles = round((pw_cycles - 2 * delay1_cycles))
    delay2_cycles = round (delay2 / (20*(10**-9)))
    recieve_time = low_cycles - 2 * delay2_cycles

    for _ in range (0, pulse_number):

        param_count += 1
        ET.SubElement(rf, 'RF' + str(param_count)).text = "1"
        ET.SubElement(sw, 'SW' + str(param_count)).text = "1"
        ET.SubElement(adc, 'ADC' + str(param_count)).text = "0"
        ET.SubElement(gru1, 'GR' + str(param_count)).text = "0"
        ET.SubElement(cl, 'CL' + str(param_count)).text = str(2 * delay1_cycles + pw_cycles)

        param_count += 1
        ET.SubElement(rf, 'RF' + str(param_count)).text = "0"
        ET.SubElement(sw, 'SW' + str(param_count)).text = "0"
        ET.SubElement(adc, 'ADC' + str(param_count)).text = "0"
        ET.SubElement(gru1, 'GR' + str(param_count)).text = "0"
        ET.SubElement(cl, 'CL' + str(param_count)).text = str(delay2_cycles)

        param_count += 1
        ET.SubElement(rf, 'RF' + str(param_count)).text = "0"
        ET.SubElement(sw, 'SW' + str(param_count)).text = "0"
        ET.SubElement(adc, 'ADC' + str(param_count)).text = "1"
        ET.SubElement(gru1, 'GR' + str(param_count)).text = "0"
        ET.SubElement(cl, 'CL' + str(param_count)).text = str(recieve_time)

        param_count += 1
        ET.SubElement(rf, 'RF'+ str(param_count)).text = "0"
        ET.SubElement(sw,'SW'+ str(param_count)).text = "0"
        ET.SubElement(adc, 'ADC' + str(param_count)).text = "0"
        ET.SubElement(gru1, 'GR' + str(param_count)).text = "0"
        ET.SubElement(cl, 'CL' + str(param_count)).text = str(delay2_cycles)

    ET.SubElement(root, 'ParamCount').text = str(param_count)
    xml_str = ET.tostring(root, encoding='utf-8', method='xml')
    parsed_str = minidom.parseString(xml_str)  # Парсим строку
    pretty_xml_str = parsed_str.toprettyxml(indent="  ")  # Добавляем отступы

    # Сохраняем форматированный XML в файл
    with open('Sync_param.xml', 'w', encoding='utf-8') as f:
        f.write(pretty_xml_str)


# Создание экземпляра QApplication, который управляет основным циклом событий и инициализацией приложения
app = QtWidgets.QApplication(sys.argv)

# Создание главного окна приложения
window = QtWidgets.QWidget()

# Установка заголовка главного окна
window.setWindowTitle("Pulse_generator")

# Установка размеров главного окна
window.resize(500, 500)

# Создание метки (надписи) с текстом
lbl = QtWidgets.QLabel("Pulse image!")

label = QtWidgets.QLabel("")
pixmap = QPixmap('pulse_template_3.jpg')
label.setPixmap(pixmap)

pulse_width_label = QtWidgets.QLabel("Pulse width")
pulse_period_label = QtWidgets.QLabel("Pulse period")
delay_label1 = QtWidgets.QLabel("Delay 1")
delay_label2 = QtWidgets.QLabel("Delay 2")
period_number_label = QtWidgets.QLabel("Pulse number")
period_number_label_2 = QtWidgets.QLabel("pulses")
sample_rate_label = QtWidgets.QLabel("Sample rate")
sample_rate_label_2 = QtWidgets.QLabel("MHz")

pulse_width_line_edit = QtWidgets.QLineEdit()
pulse_period_line_edit = QtWidgets.QLineEdit()
delay1_line_edit = QtWidgets.QLineEdit()
delay2_line_edit = QtWidgets.QLineEdit()

period_number_line_edit = QtWidgets.QLineEdit()
sample_rate_line_edit = QtWidgets.QLineEdit()

pulse_width_combo_box = QtWidgets.QComboBox()
pulse_period_combo_box = QtWidgets.QComboBox()
delay1_combo_box = QtWidgets.QComboBox()
delay2_combo_box = QtWidgets.QComboBox()
sample_rate_box = QtWidgets.QComboBox()

#Set sizing
pulse_width_label.setFixedWidth(100)
pulse_period_label.setFixedWidth(100)
delay_label1.setFixedWidth(100)
delay_label2.setFixedWidth(100)
period_number_label.setFixedWidth(100)
period_number_label_2.setFixedWidth(50)
sample_rate_label.setFixedWidth(100)
sample_rate_label_2.setFixedWidth(50)


pulse_width_line_edit.setFixedWidth(50)
pulse_period_line_edit.setFixedWidth(50)
delay1_line_edit.setFixedWidth(50)
delay2_line_edit.setFixedWidth(50)
period_number_line_edit.setFixedWidth(50)
sample_rate_box.setFixedWidth(50)

pulse_width_combo_box.setFixedWidth(50)
pulse_period_combo_box.setFixedWidth(50)
delay1_combo_box.setFixedWidth(50)
delay2_combo_box.setFixedWidth(50)
sample_rate_line_edit.setFixedWidth(50)

pulse_width_combo_box.insertItem(1,"uS")
pulse_width_combo_box.insertItem(2,"mS")
pulse_width_combo_box.insertItem(3,"S")

pulse_period_combo_box.insertItem(1,"uS")
pulse_period_combo_box.insertItem(2,"mS")
pulse_period_combo_box.insertItem(3,"S")

delay1_combo_box.insertItem(1,"nS")
delay1_combo_box.insertItem(2,"uS")
delay1_combo_box.insertItem(3,"mS")
delay1_combo_box.insertItem(4,"S")

delay2_combo_box.insertItem(1,"nS")
delay2_combo_box.insertItem(2,"uS")
delay2_combo_box.insertItem(3,"mS")
delay2_combo_box.insertItem(4,"S")

for i in range(2,21):
    sample_rate_box.insertItem(i, str(i))

#Set fonts
pulse_width_label.setFont(QFont("Open Sans",13))
pulse_period_label.setFont(QFont("Open Sans",13))
delay_label1.setFont(QFont("Open Sans",13))
delay_label2.setFont(QFont("Open Sans",13))
sample_rate_label.setFont(QFont("Open Sans",13))
period_number_label.setFont(QFont("Open Sans",13))
period_number_label_2.setFont(QFont("Open Sans",13))

pulse_width_line_edit.setFont(QFont("Open Sans",12))
pulse_period_line_edit.setFont(QFont("Open Sans",12))
delay1_line_edit.setFont(QFont("Open Sans",12))
delay2_line_edit.setFont(QFont("Open Sans",12))
sample_rate_label_2.setFont(QFont("Open Sans",13))
period_number_line_edit.setFont(QFont("Open Sans",13))

pulse_width_combo_box.setFont(QFont("Open Sans",12))
pulse_period_combo_box.setFont(QFont("Open Sans",12))
delay1_combo_box.setFont(QFont("Open Sans",12))
delay2_combo_box.setFont(QFont("Open Sans",12))
sample_rate_box.setFont(QFont("Open Sans",13))


# Создание кнопок
btn1 = QtWidgets.QPushButton("Generate")
btn2 = QtWidgets.QPushButton("Close")
btn1.setFont(QFont("Open Sans",12))
btn2.setFont(QFont("Open Sans",12))

box = QtWidgets.QVBoxLayout()
pulse_parameters_layout0 = QtWidgets.QHBoxLayout()
pulse_parameters_layout1 = QtWidgets.QHBoxLayout()
pulse_parameters_layout2 = QtWidgets.QHBoxLayout()
pulse_parameters_layout3 = QtWidgets.QHBoxLayout()
pulse_parameters_layout4 = QtWidgets.QHBoxLayout()
pulse_parameters_layout5 = QtWidgets.QHBoxLayout()
pulse_parameters_layout6 = QtWidgets.QHBoxLayout()


# Добавление метки и кнопки в вертикальный блок
pulse_parameters_layout0.addWidget(label)
box.addLayout(pulse_parameters_layout0)
pulse_parameters_layout1.addWidget(pulse_width_label)
pulse_parameters_layout1.addWidget(pulse_width_line_edit)
pulse_parameters_layout1.addWidget(pulse_width_combo_box)
box.addLayout(pulse_parameters_layout1)


pulse_parameters_layout2.addWidget(pulse_period_label)
pulse_parameters_layout2.addWidget(pulse_period_line_edit)
pulse_parameters_layout2.addWidget(pulse_period_combo_box)
box.addLayout(pulse_parameters_layout2)


pulse_parameters_layout3.addWidget(delay_label1)
pulse_parameters_layout3.addWidget(delay1_line_edit)
pulse_parameters_layout3.addWidget(delay1_combo_box)
box.addLayout(pulse_parameters_layout3)

pulse_parameters_layout6.addWidget(delay_label2)
pulse_parameters_layout6.addWidget(delay2_line_edit)
pulse_parameters_layout6.addWidget(delay2_combo_box)
box.addLayout(pulse_parameters_layout6)

pulse_parameters_layout5.addWidget(period_number_label)
pulse_parameters_layout5.addWidget(period_number_line_edit)
pulse_parameters_layout5.addWidget(period_number_label_2)
box.addLayout(pulse_parameters_layout5)


pulse_parameters_layout4.addWidget(sample_rate_label)
pulse_parameters_layout4.addWidget(sample_rate_box)
pulse_parameters_layout4.addWidget(sample_rate_label_2)
box.addLayout(pulse_parameters_layout4)


box.addWidget(btn1)
box.addWidget(btn2)


# Установка вертикального блока в качестве компоновщика главного окна
window.setLayout(box)
# Подключение обработчика события "clicked" кнопки к методу app.quit, вызывающему завершение приложения
btn1.clicked.connect(set_params)
btn2.clicked.connect(app.quit)


# Отображение главного окна
window.show()

# Запуск основного цикла обработки событий приложения
sys.exit(app.exec())  # После завершения цикла приложение выходит из программы