import tkinter as tk
from tkinter import filedialog, ttk, messagebox
import threading
import serial
import socket
import json
import os
import time
from data_sender import send_data_to_ips


class ConnectionApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Connection and Parser Application")

        # Variables
        self.connection_type = tk.StringVar(value="IP")
        self.log_file_path = tk.StringVar(value="No file selected")
        self.parser_type = tk.StringVar(value="Parser 1")
        self.ip_address = tk.StringVar(value="127.0.0.1")
        self.port = tk.IntVar(value=8080)
        self.com_port = tk.StringVar(value="COM1")
        self.baud_rate = tk.IntVar(value=9600)
        self.data = ""
        self.http_destinations = []

        # Thread control
        self.connection_thread = None
        self.is_running = False

        # UI
        self.create_widgets()

    def create_widgets(self):
        # Connection Type Selection
        tk.Label(self.root, text="Connection Type:").grid(row=0, column=0, pady=5, sticky="e")
        connection_menu = ttk.Combobox(
            self.root, textvariable=self.connection_type, values=["IP", "Log File", "COM"], state="readonly"
        )
        connection_menu.grid(row=0, column=1, pady=5, sticky="w")

        # IP Settings
        tk.Label(self.root, text="IP Address:").grid(row=1, column=0, pady=5, sticky="e")
        tk.Entry(self.root, textvariable=self.ip_address).grid(row=1, column=1, pady=5, sticky="w")

        tk.Label(self.root, text="Port:").grid(row=2, column=0, pady=5, sticky="e")
        tk.Entry(self.root, textvariable=self.port).grid(row=2, column=1, pady=5, sticky="w")

        # Log File Selection
        tk.Label(self.root, text="Log File:").grid(row=3, column=0, pady=5, sticky="e")
        tk.Button(self.root, text="Select File", command=self.select_log_file).grid(row=3, column=1, pady=5, sticky="w")
        tk.Label(self.root, textvariable=self.log_file_path).grid(row=4, column=0, columnspan=2, sticky="w")

        # COM Port Settings
        tk.Label(self.root, text="COM Port:").grid(row=5, column=0, pady=5, sticky="e")
        tk.Entry(self.root, textvariable=self.com_port).grid(row=5, column=1, pady=5, sticky="w")

        tk.Label(self.root, text="Baud Rate:").grid(row=6, column=0, pady=5, sticky="e")
        tk.Entry(self.root, textvariable=self.baud_rate).grid(row=6, column=1, pady=5, sticky="w")

        # Parser Selection
        tk.Label(self.root, text="Parser:").grid(row=7, column=0, pady=5, sticky="e")
        parser_menu = ttk.Combobox(
            self.root, textvariable=self.parser_type, values=["Parser 1", "Parser 2", "Parser 3"], state="readonly"
        )
        parser_menu.grid(row=7, column=1, pady=5, sticky="w")

        # Control Buttons
        tk.Button(self.root, text="Start", command=self.start_connection).grid(row=8, column=0, pady=10)
        tk.Button(self.root, text="Stop", command=self.stop_connection).grid(row=8, column=1, pady=10)

        # Destination Management
        tk.Button(self.root, text="Add HTTP Destination", command=self.add_http_destination).grid(row=9, column=0, pady=10)
        tk.Button(self.root, text="Show Destinations", command=self.show_destinations).grid(row=9, column=1, pady=10)

    def select_log_file(self):
        file_path = filedialog.askopenfilename(
            title="Select Log File", filetypes=[("Log files", "*.log"), ("All files", "*.*")]
        )
        if file_path:
            self.log_file_path.set(file_path)

    def start_connection(self):
        if self.connection_thread and self.connection_thread.is_alive():
            messagebox.showinfo("Info", "Connection is already running.")
            return

        self.is_running = True
        connection_type = self.connection_type.get()

        if connection_type == "IP":
            self.connection_thread = threading.Thread(target=self.connect_via_ip, daemon=True)
        elif connection_type == "Log File":
            self.connection_thread = threading.Thread(target=self.read_log_file, daemon=True)
        elif connection_type == "COM":
            self.connection_thread = threading.Thread(target=self.connect_via_com, daemon=True)
        else:
            messagebox.showerror("Error", "Unknown connection type.")
            return

        self.connection_thread.start()

    def stop_connection(self):
        self.is_running = False
        if self.connection_thread and self.connection_thread.is_alive():
            self.connection_thread.join()
        messagebox.showinfo("Info", "Connection stopped.")

    def connect_via_ip(self):
        try:
            with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
                s.connect((self.ip_address.get(), self.port.get()))
                while self.is_running:
                    data = s.recv(1024).decode()
                    self.process_data(data)
        except Exception as e:
            messagebox.showerror("Error", f"IP connection error: {e}")

    def read_log_file(self):
        try:
            with open(self.log_file_path.get(), "r") as file:
                while self.is_running:
                    line = file.readline()
                    if not line:
                        time.sleep(0.1)
                        continue
                    self.process_data(line)
        except Exception as e:
            messagebox.showerror("Error", f"Log file error: {e}")

    def connect_via_com(self):
        try:
            with serial.Serial(self.com_port.get(), self.baud_rate.get(), timeout=1) as ser:
                while self.is_running:
                    data = ser.readline().decode()
                    self.process_data(data)
        except Exception as e:
            messagebox.showerror("Error", f"COM port error: {e}")

    def process_data(self, data):
        parser = self.get_parser(self.parser_type.get())
        parsed_data = parser(data)
        self.data = parsed_data
        send_data_to_ips(parsed_data, self.http_destinations)

    def get_parser(self, parser_name):
        if parser_name == "Parser 1":
            return lambda x: {"parsed": f"Parser 1 processed {x}"}
        elif parser_name == "Parser 2":
            return lambda x: {"parsed": f"Parser 2 processed {x}"}
        elif parser_name == "Parser 3":
            return lambda x: {"parsed": f"Parser 3 processed {x}"}
        else:
            return lambda x: {"error": "No valid parser selected"}

    def add_http_destination(self):
        ip = tk.simpledialog.askstring("Add HTTP Destination", "Enter IP (http://<ip>:port):")
        if ip:
            self.http_destinations.append(ip)

    def show_destinations(self):
        messagebox.showinfo("HTTP Destinations", "\n".join(self.http_destinations))


if __name__ == "__main__":
    root = tk.Tk()
    app = ConnectionApp(root)
    root.mainloop()
