import socket
import threading
import tkinter as tk
from tkinter import filedialog
import logging
import time

logging.basicConfig(filename='TCPClient.log', level=logging.INFO, format='%(asctime)s:%(levelname)s:%(message)s')

packet_file_path = ''
send_thread = None
stop_send_flag = False

def read_hex_packets(file_path):
    packets = []
    try:
        with open(file_path, "r") as f:
            lines = f.readlines()
            for line in lines:
                line = line.strip()
                if not line:
                    continue
                try:
                    packet = bytes.fromhex(line)
                except ValueError:
                    logging.error("Invalid packet format: %s", line)
                    continue
                packets.append(packet)
    except IOError as e:
        logging.error("Failed to read file %s: %s", file_path, str(e))
    return packets

def send_packets():
    global stop_send_flag
    server_ip = server_ip_entry.get()
    server_port = int(server_port_entry.get())
    wait_for_response = wait_for_response_var.get()
    send_interval = int(send_interval_entry.get())
    loop_send = loop_send_var.get()

    packets = read_hex_packets(packet_file_path)

    try:
        client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    except socket.error as e:
        logging.error("Failed to create socket: %s", str(e))
        return

    try:
        client_socket.connect((server_ip, server_port))

        text.delete(1.0,tk.END)
        response_text.delete(1.0,tk.END)

        while not stop_send_flag:
            for i, packet in enumerate(packets):
                try:
                    client_socket.sendall(packet)
                except socket.error as e:
                    logging.error("Failed to send packet %d: %s", i+1, str(e))
                    text.insert(tk.END, "Failed to send packet %d: %s\n" % (i+1, str(e)))
                    continue
                logging.info("Sent packet %d: %s", i+1, packet.hex())
                text.insert(tk.END, "Sent packet %d: %s\n" % (i+1, packet.hex()))

                if wait_for_response:
                    try:
                        response_packet = client_socket.recv(1024)
                        logging.info("Received response for packet %d: %s", i+1, response_packet.hex())
                        response_text.insert(tk.END, response_packet.hex() + "\n")
                    except socket.error as e:
                        logging.error("Failed to receive response for packet %d: %s", i+1, str(e))
                        response_text.insert(tk.END, "Failed to receive response for packet %d: %s\n" % (i+1, str(e)))

                if i != len(packets)-1:
                    time.sleep((send_interval + 500) / 1000)

            if not loop_send:
                break

    except socket.error as e:
        logging.error(str(e))

    finally:
        client_socket.close()

def start_send():
    global stop_send_flag, send_thread
    stop_send_flag = False
    send_thread = threading.Thread(target=send_packets)
    send_thread.start()

def stop_send():
    global stop_send_flag
    stop_send_flag = True

def open_file_dialog():
    global packet_file_path
    packet_file_path = filedialog.askopenfilename(filetypes=(("Text files", "*.txt"),))
    file_path_label.config(text=packet_file_path)

root = tk.Tk()
root.title("TCP Client")

server_frame = tk.Frame()
server_frame.pack(side=tk.TOP, padx=10, pady=10)
server_ip_label = tk.Label(server_frame, text="Server IP: ")
server_ip_label.pack(side=tk.LEFT)
server_ip_entry = tk.Entry(server_frame, width=15)
server_ip_entry.pack(side=tk.LEFT)
server_port_label = tk.Label(server_frame, text="Server Port: ")
server_port_label.pack(side=tk.LEFT)
server_port_entry = tk.Entry(server_frame, width=5)
server_port_entry.pack(side=tk.LEFT)

file_frame = tk.Frame()
file_frame.pack(side=tk.TOP, padx=10, pady=10)
open_file_button = tk.Button(file_frame, text="Choose Packet File", command=open_file_dialog)
open_file_button.pack(side=tk.LEFT)
file_path_label = tk.Label(file_frame, text="No file selected")
file_path_label.pack(side=tk.LEFT, padx=10)
send_interval_label = tk.Label(file_frame, text="Packet Send Interval (ms): ")
send_interval_label.pack(side=tk.LEFT)
send_interval_entry = tk.Entry(file_frame, width=5)
send_interval_entry.pack(side=tk.LEFT)

wait_for_response_var = tk.BooleanVar()
wait_for_response_checkbox = tk.Checkbutton(root, text="Wait for Response after Sending each Packet", variable=wait_for_response_var)
wait_for_response_checkbox.pack(side=tk.TOP)

loop_send_var = tk.BooleanVar()
loop_send_checkbox = tk.Checkbutton(root, text="Loop Send Packets", variable=loop_send_var)
loop_send_checkbox.pack(side=tk.TOP)

text_frame = tk.Frame()
text_frame.pack(side=tk.TOP, padx=10, pady=10)
text = tk.Text(text_frame, height=10, width=50)
text.pack(side=tk.LEFT)
response_text = tk.Text(text_frame, height=10, width=50)
response_text.pack(side=tk.RIGHT)

control_frame = tk.Frame()
control_frame.pack(side=tk.BOTTOM, padx=10, pady=10)
start_button = tk.Button(control_frame, text="Start Sending", command=start_send)
start_button.pack(side=tk.LEFT)
stop_button = tk.Button(control_frame, text="Stop Sending", command=stop_send)
stop_button.pack(side=tk.LEFT)

root.mainloop()