import tkinter as tk
from tkinter import scrolledtext, messagebox, ttk
import threading
import time
import ctypes

try:
    ctypes.windll.shcore.SetProcessDpiAwareness(2)
except:
    try:
        ctypes.windll.user32.SetProcessDPIAware()
    except:
        pass

try:
    import pyautogui
    pyautogui.FAILSAFE = True
    PYAUTOGUI_AVAILABLE = True
except ImportError:
    PYAUTOGUI_AVAILABLE = False

THEMES = {
    'Dark':   ('#1e1e2e','#2a2a3e','#cdd6f4','#89b4fa','#22c55e','#6c7086'),
    'Light':  ('#f5f5f5','#ffffff','#1e1e2e','#2563eb','#16a34a','#6b7280'),
    'Purple': ('#1a0a2e','#2d1b4e','#e2d9f3','#a855f7','#8b5cf6','#7c6f9f'),
    'Ocean':  ('#0c1e35','#112844','#e2e8f0','#38bdf8','#0ea5e9','#4a7fa0'),
    'Green':  ('#0a1a0f','#132218','#dcfce7','#22c55e','#16a34a','#4a7a58'),
}
SPEEDS = [('Very Fast ~600 WPM',10),('Fast ~240 WPM',50),('Human ~80 WPM',150),('Slow ~48 WPM',250),('Very Slow ~30 WPM',400)]
DELAYS = [('2 sec',2),('3 sec',3),('5 sec',5),('10 sec',10)]

class AutoTyper:
    def __init__(self, root):
        self.root = root
        self.root.title("Auto Typer")
        self.root.resizable(False, False)
        self.root.attributes('-topmost', True)
        self.is_typing = False
        self.stop_flag = False
        self.theme_idx = 0
        self.speed_idx = 2
        self.delay_idx = 1
        self._build()
        self._apply_theme()
        self.root.update_idletasks()
        w,h=420,480
        sw=self.root.winfo_screenwidth()
        sh=self.root.winfo_screenheight()
        self.root.geometry(f"{w}x{h}+{(sw-w)//2}+{(sh-h)//2}")

    def _bg(self): return THEMES[list(THEMES)[self.theme_idx]][0]
    def _sur(self): return THEMES[list(THEMES)[self.theme_idx]][1]
    def _txt(self): return THEMES[list(THEMES)[self.theme_idx]][2]
    def _acc(self): return THEMES[list(THEMES)[self.theme_idx]][3]
    def _btn(self): return THEMES[list(THEMES)[self.theme_idx]][4]
    def _mut(self): return THEMES[list(THEMES)[self.theme_idx]][5]

    def _build(self):
        r = self.root
        self.title_frame = tk.Frame(r)
        self.title_frame.pack(fill='x')
        self.title_lbl = tk.Label(self.title_frame, text="⌨️  Auto Typer", font=('Segoe UI',13,'bold'), padx=12, pady=8, anchor='w')
        self.title_lbl.pack(side='left')
        self.theme_lbl = tk.Label(self.title_frame, text="Dark", font=('Segoe UI',8), padx=4)
        self.theme_lbl.pack(side='right')
        self.theme_btn = tk.Button(self.title_frame, text="🎨", font=('Segoe UI',11), relief='flat', cursor='hand2', padx=8, pady=4, command=self.cycle_theme)
        self.theme_btn.pack(side='right', padx=6)
        self.text_frame = tk.Frame(r, padx=10, pady=4)
        self.text_frame.pack(fill='both', expand=True)
        self.text_lbl = tk.Label(self.text_frame, text="Text to type:", font=('Segoe UI',8), anchor='w')
        self.text_lbl.pack(fill='x')
        self.text_box = tk.Text(self.text_frame, font=('Consolas',10), height=9, relief='flat', padx=8, pady=8, wrap='word')
        self.text_box.pack(fill='both', expand=True)
        self.text_box.bind('<KeyRelease>', self._update_stats)
        self.stats_frame = tk.Frame(r, padx=10)
        self.stats_frame.pack(fill='x')
        self.stats_lbl = tk.Label(self.stats_frame, text="0 chars  |  0 words  |  ~0s", font=('Segoe UI',8), anchor='w')
        self.stats_lbl.pack(side='left')
        self.quick_start_btn = tk.Button(self.stats_frame, text="▶ Start", font=('Segoe UI',8,'bold'), relief='flat', cursor='hand2', padx=8, pady=1, command=self.start, bg='#22c55e', fg='white', activebackground='#16a34a')
        self.quick_start_btn.pack(side='right', padx=(4,0))
        self.clear_btn = tk.Button(self.stats_frame, text="Clear", font=('Segoe UI',8), relief='flat', cursor='hand2', padx=8, pady=1, command=self.clear, bg='#ef4444', fg='white', activebackground='#dc2626')
        self.clear_btn.pack(side='right')
        self.speed_frame = tk.Frame(r, padx=10, pady=4)
        self.speed_frame.pack(fill='x')
        self.speed_lbl = tk.Label(self.speed_frame, text="Speed:", font=('Segoe UI',8), width=7, anchor='w')
        self.speed_lbl.pack(side='left')
        self.speed_btns = []
        for i,(label,_) in enumerate(SPEEDS):
            short = label.split('~')[0].strip()
            b = tk.Button(self.speed_frame, text=short, font=('Segoe UI',7), relief='flat', cursor='hand2', padx=6, pady=3, command=lambda x=i: self.set_speed(x))
            b.pack(side='left', padx=2)
            self.speed_btns.append(b)
        self.delay_frame = tk.Frame(r, padx=10, pady=2)
        self.delay_frame.pack(fill='x')
        self.delay_lbl = tk.Label(self.delay_frame, text="Delay:", font=('Segoe UI',8), width=7, anchor='w')
        self.delay_lbl.pack(side='left')
        self.delay_btns = []
        for i,(label,_) in enumerate(DELAYS):
            b = tk.Button(self.delay_frame, text=label, font=('Segoe UI',7), relief='flat', cursor='hand2', padx=6, pady=3, command=lambda x=i: self.set_delay(x))
            b.pack(side='left', padx=2)
            self.delay_btns.append(b)
        self.prog_frame = tk.Frame(r, padx=10, pady=4)
        self.prog_frame.pack(fill='x')
        style = ttk.Style()
        style.theme_use('clam')
        style.configure('at.Horizontal.TProgressbar', troughcolor='#2a2a3e', background='#22c55e', bordercolor='#2a2a3e')
        self.progress = ttk.Progressbar(self.prog_frame, mode='determinate', maximum=100, style='at.Horizontal.TProgressbar')
        self.progress.pack(fill='x')
        self.btn_frame = tk.Frame(r, padx=10, pady=6)
        self.btn_frame.pack(fill='x')
        self.start_btn = tk.Button(self.btn_frame, text="▶  START", font=('Segoe UI',11,'bold'), relief='flat', cursor='hand2', pady=10, command=self.start, fg='white', activeforeground='white')
        self.start_btn.pack(side='left', fill='x', expand=True, padx=(0,4))
        self.stop_btn = tk.Button(self.btn_frame, text="⏹  STOP", font=('Segoe UI',11,'bold'), relief='flat', cursor='hand2', pady=10, command=self.stop, state='disabled', bg='#ef4444', fg='white', activebackground='#dc2626', activeforeground='white')
        self.stop_btn.pack(side='left', fill='x', expand=True, padx=(4,0))
        self.status_var = tk.StringVar(value='✅ Ready — Paste text and click Start')
        self.status_lbl = tk.Label(r, textvariable=self.status_var, font=('Segoe UI',9), fg='#22c55e', wraplength=400)
        self.status_lbl.pack(pady=(4,0))
        self.tip_frame = tk.Frame(r, padx=10, pady=5)
        self.tip_frame.pack(fill='x')
        self.tip_lbl = tk.Label(self.tip_frame, text="Enter=Start  |  Esc=Stop  |  Move mouse top-left to abort", font=('Segoe UI',7))
        self.tip_lbl.pack()
        self.root.bind('<Return>', lambda e: self.start())
        self.root.bind('<Escape>', lambda e: self.stop())
        self.text_box.focus_set()

    def _apply_theme(self):
        bg=self._bg(); sur=self._sur(); txt=self._txt(); acc=self._acc(); btn=self._btn(); mut=self._mut()
        name=list(THEMES)[self.theme_idx]
        self.root.configure(bg=bg)
        for w in [self.title_frame,self.text_frame,self.stats_frame,self.speed_frame,self.delay_frame,self.prog_frame,self.btn_frame,self.tip_frame]:
            w.configure(bg=bg)
        self.title_lbl.configure(bg=bg,fg=txt)
        self.theme_lbl.configure(bg=bg,fg=mut,text=name)
        self.theme_btn.configure(bg=bg,fg=acc,activebackground=bg)
        self.text_lbl.configure(bg=bg,fg=mut)
        self.text_box.configure(bg=sur,fg=txt,insertbackground=acc,selectbackground=acc)
        self.stats_lbl.configure(bg=bg,fg=mut)
        self.speed_lbl.configure(bg=bg,fg=mut)
        self.delay_lbl.configure(bg=bg,fg=mut)
        self.status_lbl.configure(bg=bg)
        self.tip_lbl.configure(bg=sur,fg=mut)
        self.tip_frame.configure(bg=sur)
        for i,b in enumerate(self.speed_btns):
            b.configure(bg=acc if i==self.speed_idx else sur, fg=bg if i==self.speed_idx else txt, activebackground=acc)
        for i,b in enumerate(self.delay_btns):
            b.configure(bg=acc if i==self.delay_idx else sur, fg=bg if i==self.delay_idx else txt, activebackground=acc)
        if self.start_btn['state']=='normal':
            self.start_btn.configure(bg=btn,activebackground=acc)
        style=ttk.Style()
        style.configure('at.Horizontal.TProgressbar',troughcolor=sur)

    def cycle_theme(self):
        self.theme_idx=(self.theme_idx+1)%len(THEMES)
        self._apply_theme()

    def set_speed(self,idx):
        self.speed_idx=idx; self._apply_theme(); self._update_stats()

    def set_delay(self,idx):
        self.delay_idx=idx; self._apply_theme()

    def _update_stats(self,event=None):
        text=self.text_box.get('1.0','end-1c')
        chars=len(text); words=len(text.split()) if text.strip() else 0
        ms=SPEEDS[self.speed_idx][1]; secs=(chars*ms)//1000
        t=f"{secs}s" if secs<60 else f"{secs//60}m {secs%60}s"
        self.stats_lbl.config(text=f"{chars:,} chars  |  {words:,} words  |  ~{t}")

    def clear(self):
        self.text_box.delete('1.0','end')
        self.progress['value']=0; self._update_stats()
        self.set_status('🗑️ Cleared','#ef4444')
        self.root.after(2000,lambda:self.set_status('✅ Ready — Paste text and click Start','#22c55e'))

    def set_status(self,msg,color='#22c55e'):
        self.status_var.set(msg); self.status_lbl.config(fg=color)

    def start(self):
        if self.is_typing: return
        if not PYAUTOGUI_AVAILABLE:
            messagebox.showerror("Missing Library","Run this first:\n\npip install pyautogui\n\nThen restart.")
            return
        text=self.text_box.get('1.0','end-1c')
        if not text.strip():
            messagebox.showwarning("No Text","Paste some text first!")
            return
        self.stop_flag=False; self.is_typing=True
        t=THEMES[list(THEMES)[self.theme_idx]]
        self.start_btn.config(state='disabled',bg='#475569')
        self.stop_btn.config(state='normal')
        self.progress['value']=0
        threading.Thread(target=self._type,args=(text,),daemon=True).start()

    def _type(self,text):
        delay=DELAYS[self.delay_idx][1]; ms=SPEEDS[self.speed_idx][1]/1000.0
        for i in range(delay,0,-1):
            if self.stop_flag: self._done(True); return
            self.set_status(f'⏰ Switch to target window! Starting in {i}s...','#f59e0b')
            time.sleep(1)
        total=len(text)
        for i,char in enumerate(text):
            if self.stop_flag: self._done(True); return
            try:
                if char=='\n': pyautogui.press('enter')
                elif char=='\t': pyautogui.press('tab')
                else: pyautogui.write(char,interval=0)
            except Exception as e:
                self.set_status(f'Error: {e}','#ef4444'); self._done(True); return
            if i%5==0 or i==total-1:
                pct=(i+1)/total*100; n=i+1
                self.root.after(0,lambda p=pct,c=n:(
                    self.progress.__setitem__('value',p),
                    self.set_status(f'⌨️ {c:,}/{total:,} ({p:.0f}%)','#f59e0b')
                ))
            time.sleep(ms)
        self._done(False)

    def _done(self,stopped):
        self.is_typing=False
        t=THEMES[list(THEMES)[self.theme_idx]]
        self.root.after(0,lambda:self.start_btn.config(state='normal',bg=t[4]))
        self.root.after(0,lambda:self.stop_btn.config(state='disabled'))
        if stopped: self.root.after(0,lambda:self.set_status('⏹ Stopped.','#ef4444'))
        else:
            self.root.after(0,lambda:self.progress.__setitem__('value',100))
            self.root.after(0,lambda:self.set_status('✅ Done! All text typed.','#22c55e'))

    def stop(self):
        if self.is_typing: self.stop_flag=True

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