import threading
from models.SystemStats import SystemStats
from MainView import MainView
from models.NetworkingScanner import NetworkScanner
from models.Sniffer import packet_callback, sniff
from models.MusicPlayer import MusicPlayerModel
import tkinter as tk
import time
import datetime


class MainController:
    def __init__(self, view: MainView):
        self.view = view
        self.sniffer_thread = None
        self.sniffer_running = False
        self.connect_events()
        self.start_system_updates()
        self.music_model = MusicPlayerModel()

    def connect_events(self):
        """Conecta los eventos de la vista con las funciones del controlador."""
        self.view.button_track_ip.config(command=self.handle_track_ip)
        self.view.button_scan_network.config(command=self.start_network_scan_thread)
        self.view.button_start_sniffer.config(command=self.start_sniffer_thread)
        self.view.button_stop_sniffer.config(command=self.stop_sniffer)
        
        self.view.button_play_music.config(command=self.play_song)
        self.view.button_stop_music.config(command=self.stop_song)
        self.view.button_refresh_music.config(command=self.refresh_songs)
        
        
    def start_sniffer_thread(self):
        """Inicia el sniffer en un hilo separado."""
        def run_sniffer():
            self.sniffer_running = True
            while self.sniffer_running:
                try:
                    sniff(prn=self.process_packet, filter="ip", store=0, timeout=1)
                except Exception as e:
                    self.view.text_sniffer_output.insert(tk.END, f"Error: {str(e)}\n")
        
        # Configurar botones
        self.view.button_start_sniffer.config(state="disabled")
        self.view.button_stop_sniffer.config(state="normal")

        # Iniciar el hilo del sniffer
        self.sniffer_thread = threading.Thread(target=run_sniffer, daemon=True)
        self.sniffer_thread.start()
        

    def stop_sniffer(self):
        """Detiene el sniffer."""
        self.sniffer_running = False
        self.view.button_start_sniffer.config(state="normal")
        self.view.button_stop_sniffer.config(state="disabled")
        self.view.text_sniffer_output.insert(tk.END, "Sniffer detenido.\n")


    def process_packet(self, packet):
        """Procesa un paquete capturado y lo muestra en la interfaz."""
        packet_info = packet_callback(packet)
        self.view.text_sniffer_output.insert(tk.END, f"{packet_info}\n")
        self.view.text_sniffer_output.see(tk.END)  # Scroll automático
    
    def start_network_scan_thread(self):
        """Inicia un hilo para escanear la red continuamente cada 5 segundos."""
        def scan_network_periodically():
            network_range = NetworkScanner.get_network_range()
            while True:
                print("Scanning....")
                devices = NetworkScanner.scan_network(network_range)
                self.display_network_scan_results(devices)
                

        # Inicia un hilo para el escaneo continuo
        threading.Thread(target=scan_network_periodically, daemon=True).start()

    def handle_track_ip(self):
        """Maneja el evento de rastrear una IP."""
        ip = self.view.entry_ip.get()  # Obtener la IP ingresada
        if not ip:
            self.view.text_output.insert(tk.END, "Por favor, introduce una IP válida.\n")
            return

        # Ejecutar fetch_ip_data en un hilo
        def fetch_ip_data():
            try:
                result = SystemStats.track_ip(ip)  # Llamar a la función con la IP
                if "error" in result:
                    self.view.text_output.insert(tk.END, f"Error: {result['error']}\n")
                else:
                    self.display_ip_data(result)
            except Exception as e:
                self.view.text_output.insert(tk.END, f"Error al rastrear la IP: {e}\n")

        threading.Thread(target=fetch_ip_data, daemon=True).start()

        
    def display_network_scan_results(self, devices):
        """Muestra los resultados del escaneo en la interfaz."""
        # Limpiar el texto anterior y mostrar los nuevos resultados
        self.view.text_network_scan.delete('1.0', tk.END)
        self.view.text_network_scan.insert(tk.END, "Dispositivos encontrados:\n")
        for device in devices:
            self.view.text_network_scan.insert(tk.END, f"IP: {device['ip']}, MAC: {device['mac']}\n")
            
    def display_ip_data(self, data):
        """Muestra la información de la IP en el área de texto."""
        self.view.text_output.insert(tk.END, f"IP: {data['ip']}\n")
        self.view.text_output.insert(tk.END, f"Tipo: {data['type']}\n")
        self.view.text_output.insert(tk.END, f"País: {data['country']} ({data['country_code']})\n")
        self.view.text_output.insert(tk.END, f"Región: {data['region']} ({data['region_code']})\n")
        self.view.text_output.insert(tk.END, f"Ciudad: {data['city']}\n")
        self.view.text_output.insert(tk.END, f"Latitud: {data['latitude']}\n")
        self.view.text_output.insert(tk.END, f"Longitud: {data['longitude']}\n")
        self.view.text_output.insert(tk.END, f"Mapa: https://www.google.com/maps/@{data['latitude']},{data['longitude']},8z\n")
        self.view.text_output.insert(tk.END, "=============================================\n")

    def start_system_updates(self):
        """Inicia las actualizaciones periódicas del sistema."""
        threading.Thread(target=self.update_system_stats, daemon=True).start()
        self.update_time()

    def update_time(self):
        """Actualiza el reloj en la barra de estado."""
        now = datetime.datetime.now()
        time_str = now.strftime("%H:%M:%S")
        date_str = now.strftime("%Y-%m-%d")
        day_of_week = now.strftime("%A")
        self.view.label_fecha_hora.config(text=f"{day_of_week}, {date_str} - {time_str}")
        self.view.root.after(1000, self.update_time)  # Actualizar cada segundo

    def update_system_stats(self):
        """Actualiza las estadísticas del sistema periódicamente en un hilo."""
        while True:
            # Obtener estadísticas del sistema
            cpu_usage = SystemStats.get_cpu_usage()
            memory_usage = SystemStats.get_memory_usage()
            bytes_sent, bytes_recv = SystemStats.get_network_usage()

            # Actualizar etiquetas en el hilo principal
            self.view.root.after(0, self.view.label_cpu.config, {"text": f"Uso CPU: {cpu_usage:.2f}%"})
            self.view.root.after(0, self.view.label_uso_memoria.config, {"text": f"Uso RAM: {memory_usage:.2f}%"})
            self.view.root.after(0, self.view.label_bytes_sent.config, {"text": f"Subida: {bytes_sent / 1024:.2f} KB/s"})
            self.view.root.after(0, self.view.label_bytes_recv.config, {"text": f"Descarga: {bytes_recv / 1024:.2f} KB/s"})

            time.sleep(1)  # Esperar 1 segundo antes de actualizar nuevamente
            
            
    def load_songs(self):
        """Carga las canciones desde el modelo y las envía a la vista."""
        self.songs, self.message = self.music_model.load_songs()
        self.view.populate_music_player(self.songs)

    def play_song(self):
        """Reproduce la canción seleccionada."""
        selected = self.view.music_listbox.curselection()
        if not selected:
            self.view.root.bell()
            return
        song_name = self.view.music_listbox.get(selected)
        message = self.music_model.play_song(song_name)
        print(f"Reproduciendo: {message}")

    def stop_song(self):
        """Detiene la reproducción de la canción."""
        message = self.music_model.stop_song()
        print(f"Detenido: {message}")

    def refresh_songs(self):
        """Actualiza la lista de canciones disponibles."""
        self.load_songs()
        print(self.message)

