import sys
import os
import tkinter as tk
from tkinter import ttk
import datetime

# ---------------------------------------------------------------------------
# 1. LECTURA DE ARGUMENTOS
# ---------------------------------------------------------------------------
if len(sys.argv) < 7:
    print("Uso: python chat_client.py <mi_nombre> <otro_nombre> <f_salida> <f_entrada> <x> <y>")
    sys.exit(1)

MY_NAME    = sys.argv[1]   # Nombre de este cliente (ej: "Cliente A")
OTHER_NAME = sys.argv[2]   # Nombre del otro cliente (ej: "Cliente B")
FILE_OUT   = sys.argv[3]   # Fichero donde YO escribo mis mensajes
FILE_IN    = sys.argv[4]   # Fichero donde YO leo los mensajes del otro
X_POS      = int(sys.argv[5])  # Posición horizontal de la ventana
Y_POS      = int(sys.argv[6])  # Posición vertical de la ventana

# ---------------------------------------------------------------------------
# 2. COMUNICACIÓN IPC POR FICHERO
# ---------------------------------------------------------------------------

# Contador de líneas ya leídas. Así en cada polling solo procesamos
# las líneas NUEVAS, no releemos todo el fichero desde el principio.
lines_read = 0

def write_message(text):
    """
    Escribe un mensaje en el fichero de salida (el que lee el otro cliente).
    Formato de cada línea: HH:MM|texto\n
    Usamos modo "a" (append) para no borrar mensajes anteriores.
    """
    with open(FILE_OUT, "a", encoding="utf-8") as f:
        timestamp = datetime.datetime.now().strftime("%H:%M")
        f.write(f"{timestamp}|{text}\n")

def read_new_messages():
    """
    Lee el fichero de entrada y devuelve SOLO las líneas nuevas
    desde la última vez que se llamó a esta función.
    Devuelve una lista de tuplas (timestamp, texto).
    """
    global lines_read
    new = []
    try:
        with open(FILE_IN, "r", encoding="utf-8") as f:
            all_lines = f.readlines()
        # Solo procesamos desde la línea lines_read en adelante
        for line in all_lines[lines_read:]:
            line = line.strip()
            if line and "|" in line:
                ts, msg = line.split("|", 1)  # Separamos timestamp del texto
                new.append((ts, msg))
        # Actualizamos el contador para la próxima llamada
        lines_read = len(all_lines)
    except Exception:
        pass  # Si el fichero no existe aún, simplemente no hay mensajes
    return new

# ---------------------------------------------------------------------------
# 3. INTERFAZ GRÁFICA (Tkinter)
# ---------------------------------------------------------------------------

COLOR_BG       = "#F0F4F8"   # Fondo general (gris claro)
COLOR_HEADER   = "#2C3E50"   # Cabecera (azul oscuro)
COLOR_MY_BG    = "#DCF8C6"   # Burbujas propias (verde tipo WhatsApp)
COLOR_OTHER_BG = "#FFFFFF"   # Burbujas del otro (blanco)
COLOR_SEND_BTN = "#25D366"   # Botón enviar (verde)
FONT_MSG       = ("Segoe UI", 10)
FONT_HEADER    = ("Segoe UI", 12, "bold")

root = tk.Tk()
root.title(f"Chat — {MY_NAME}")
root.geometry(f"500x700+{X_POS}+{Y_POS}")  # Tamaño y posición inicial
root.minsize(360, 400)                       # Tamaño mínimo para que no se deforme
root.resizable(True, True)
root.configure(bg=COLOR_BG)

# --- Layout con grid: 3 filas ---
# fila 0 = cabecera  (altura fija,   weight=0)
# fila 1 = mensajes  (crece/encoge,  weight=1)
# fila 2 = input     (altura fija,   weight=0)
# Usar weight=0 en las filas del input y cabecera garantiza que
# siempre tienen su espacio reservado sin importar el tamaño de la ventana.
root.grid_rowconfigure(0, weight=0)
root.grid_rowconfigure(1, weight=1)
root.grid_rowconfigure(2, weight=0)
root.grid_columnconfigure(0, weight=1)

# --- FILA 0: Cabecera ---
header = tk.Frame(root, bg=COLOR_HEADER, pady=10)
header.grid(row=0, column=0, sticky="ew")

tk.Label(
    header,
    text=f"💬  {MY_NAME}  →  {OTHER_NAME}",
    bg=COLOR_HEADER, fg="white",
    font=FONT_HEADER, anchor="w", padx=15
).pack(side="left")

tk.Label(
    header, text="● Conectado",
    bg=COLOR_HEADER, fg="#2ECC71",
    font=("Segoe UI", 9)
).pack(side="right", padx=15)

# --- FILA 1: Área de mensajes (Canvas con scroll) ---
# Usamos un Canvas porque tk.Frame no tiene scrollbar nativa.
# El truco es poner un Frame dentro del Canvas y ajustar su ancho
# al del Canvas cada vez que este cambia de tamaño (on_canvas_configure).
messages_outer = tk.Frame(root, bg=COLOR_BG)
messages_outer.grid(row=1, column=0, sticky="nsew", padx=8, pady=(8, 4))
messages_outer.grid_rowconfigure(0, weight=1)
messages_outer.grid_columnconfigure(0, weight=1)

canvas_msgs = tk.Canvas(messages_outer, bg=COLOR_BG, highlightthickness=0)
canvas_msgs.grid(row=0, column=0, sticky="nsew")

scrollbar = ttk.Scrollbar(messages_outer, command=canvas_msgs.yview)
scrollbar.grid(row=0, column=1, sticky="ns")
canvas_msgs.configure(yscrollcommand=scrollbar.set)

# Frame real donde se añaden las burbujas de mensaje
messages_frame = tk.Frame(canvas_msgs, bg=COLOR_BG)
canvas_window = canvas_msgs.create_window((0, 0), window=messages_frame, anchor="nw")

def on_frame_configure(event):
    """Actualiza la zona de scroll cuando el frame de mensajes cambia de tamaño."""
    canvas_msgs.configure(scrollregion=canvas_msgs.bbox("all"))

def on_canvas_configure(event):
    """Ajusta el ancho del frame interior al ancho del canvas (responsivo)."""
    canvas_msgs.itemconfig(canvas_window, width=event.width)

messages_frame.bind("<Configure>", on_frame_configure)
canvas_msgs.bind("<Configure>", on_canvas_configure)

# Mensaje de sistema al inicio del chat
tk.Label(
    messages_frame,
    text=f"── Inicio del chat con {OTHER_NAME} ──",
    bg=COLOR_BG, fg="#AAAAAA",
    font=("Segoe UI", 9, "italic")
).pack(pady=(10, 5))

def add_bubble(text, is_mine, timestamp=None):
    """
    Añade una burbuja de mensaje al área de chat.
    - is_mine=True  → burbuja verde a la derecha (mensaje propio)
    - is_mine=False → burbuja blanca a la izquierda (mensaje recibido)
    """
    if timestamp is None:
        timestamp = datetime.datetime.now().strftime("%H:%M")

    bg_color = COLOR_MY_BG   if is_mine else COLOR_OTHER_BG
    side     = "right"       if is_mine else "left"
    anchor   = "e"           if is_mine else "w"
    label    = "Tú"          if is_mine else OTHER_NAME

    # Fila contenedora (ocupa todo el ancho para poder alinear la burbuja)
    row = tk.Frame(messages_frame, bg=COLOR_BG)
    row.pack(fill="x", pady=3, padx=8)

    # Burbuja real (solo tan ancha como su contenido)
    bubble = tk.Frame(row, bg=bg_color, padx=10, pady=6)
    bubble.pack(side=side, anchor=anchor)

    tk.Label(bubble, text=label,     bg=bg_color, fg="#888888",
             font=("Segoe UI", 8, "bold")).pack(anchor="w")
    tk.Label(bubble, text=text,      bg=bg_color, fg="#222222",
             font=FONT_MSG, wraplength=280, justify="left").pack(anchor="w")
    tk.Label(bubble, text=timestamp, bg=bg_color, fg="#AAAAAA",
             font=("Segoe UI", 7)).pack(anchor="e")

    # Scroll automático al fondo al recibir/enviar un mensaje
    root.after(50, lambda: canvas_msgs.yview_moveto(1.0))

# --- FILA 2: Área de entrada de texto ---
input_frame = tk.Frame(root, bg="#E8ECF0", pady=8, padx=8)
input_frame.grid(row=2, column=0, sticky="ew")
input_frame.grid_columnconfigure(0, weight=1)

text_entry = tk.Text(
    input_frame,
    height=3,                    # 3 líneas de alto
    font=FONT_MSG,
    bg="#FFFFFF", fg="#222222",
    relief="flat", wrap="word",
    padx=8, pady=6,
    bd=1,
    highlightbackground="#CCCCCC",
    highlightthickness=1
)
text_entry.grid(row=0, column=0, sticky="ew", padx=(0, 8))

def send_message(event=None):
    """
    Recoge el texto del entry, lo escribe en el fichero de salida
    y añade la burbuja propia en pantalla.
    Devuelve "break" para que el Enter no inserte un salto de línea.
    """
    msg = text_entry.get("1.0", "end-1c").strip()
    if not msg:
        return "break"
    write_message(msg)              # Escribe en el fichero de cola
    add_bubble(msg, is_mine=True)   # Muestra la burbuja en nuestra ventana
    text_entry.delete("1.0", "end") # Limpia el campo de texto
    return "break"

# Enter envía el mensaje; Shift+Enter inserta salto de línea
text_entry.bind("<Return>", send_message)
text_entry.bind("<Shift-Return>", lambda e: None)

tk.Button(
    input_frame,
    text="Enviar ➤",
    bg=COLOR_SEND_BTN, fg="white",
    font=("Segoe UI", 10, "bold"),
    relief="flat", padx=12, pady=8,
    cursor="hand2",
    command=send_message
).grid(row=0, column=1)

# ---------------------------------------------------------------------------
# 4. POLLING DE MENSAJES ENTRANTES
# ---------------------------------------------------------------------------
def poll_incoming():
    new_msgs = read_new_messages()
    for ts, msg in new_msgs:
        add_bubble(msg, is_mine=False, timestamp=ts)  # Burbuja del otro
    root.after(300, poll_incoming)  # Volvemos a llamarnos en 300ms

root.after(300, poll_incoming)  # Primera llamada al arrancar

# ---------------------------------------------------------------------------
# 5. BUCLE PRINCIPAL
# ---------------------------------------------------------------------------
root.mainloop()