# -*- coding: utf-8 -*-
"""
פותח את הדפדפן האמיתי שלך עם פרופיל שתבחר (עם כל ההתחברויות שלך),
נכנס לאתר וכותב טקסט בשדה שמסומן בדף.
אפשר להפעיל אחרי השהיה או בשעה מסוימת, ולשמור על המחשב ער עד אז.
בלי ספריות חיצוניות - רק פייתון רגיל ל-Windows.
"""
import base64
import ctypes
import json
import os
import subprocess
import time
import tkinter as tk
from ctypes import wintypes
from datetime import datetime, timedelta
from tkinter import ttk, messagebox

# ---- ברירות מחדל (אפשר לשנות גם בחלון) ----
DEFAULT_URL = "https://claude.ai/new"
DEFAULT_TEXT = "לילה טוב"
DEFAULT_START_DELAY = 10   # שניות מהלחיצה על "התחל" עד פתיחת הדפדפן
DEFAULT_MIN_WAIT = 3       # שניות המתנה מינימליות אחרי פתיחת הדפדפן, לפני הניסיון הראשון
DEFAULT_MAX_WAIT = 60      # מקסימום שניות לחכות שהדף יהיה מוכן להקלדה
RETRY_EVERY_MS = 2000      # כל כמה זמן לנסות שוב אם הדף עוד לא מוכן

# בודק דרך UI Automation של Windows אם הפוקוס נמצא בתוך דף אינטרנט (רכיב Document),
# ולא בשורת הכתובת. נבדק בכרום: שדה בדף = PAGE, שורת הכתובת = OUT.
# UIAERR = הבדיקה רצה אבל הדף עוד לא ענה (קורה בזמן טעינה), וזה נחשב "עוד לא מוכן".
# אם לא חזרה אף אחת מהתשובות האלה, PowerShell עצמו לא הצליח לרוץ.
FOCUS_CHECK_PS = r"""
$ErrorActionPreference = 'Stop'
Add-Type -AssemblyName UIAutomationClient, UIAutomationTypes
try {
    $doc = [System.Windows.Automation.ControlType]::Document
    $w = [System.Windows.Automation.TreeWalker]::ControlViewWalker
    $e = [System.Windows.Automation.AutomationElement]::FocusedElement
    for ($i = 0; $i -lt 50 -and $e -ne $null; $i++) {
        if ($e.Current.ControlType -eq $doc) { 'PAGE'; exit }
        $e = $w.GetParent($e)
    }
    'OUT'
} catch {
    'UIAERR'
}
"""
CHECK_FAILURES_LIMIT = 2  # אחרי כמה כשלים רצופים של PowerShell מוותרים
CREATE_NO_WINDOW = 0x08000000  # כדי שחלון PowerShell לא יקפוץ ויגנוב את הפוקוס

LOCAL = os.environ.get("LOCALAPPDATA", "")
PROGRAM_DIRS = [
    os.environ.get("ProgramFiles", r"C:\Program Files"),
    os.environ.get("ProgramFiles(x86)", r"C:\Program Files (x86)"),
    LOCAL,
]

# (שם, תיקיית הפרופילים, נתיב יחסי לקובץ ההרצה)
BROWSERS = [
    ("Chrome", os.path.join(LOCAL, r"Google\Chrome\User Data"), r"Google\Chrome\Application\chrome.exe"),
    ("Edge", os.path.join(LOCAL, r"Microsoft\Edge\User Data"), r"Microsoft\Edge\Application\msedge.exe"),
    ("Brave", os.path.join(LOCAL, r"BraveSoftware\Brave-Browser\User Data"), r"BraveSoftware\Brave-Browser\Application\brave.exe"),
]


def find_exe(rel):
    for base in PROGRAM_DIRS:
        path = os.path.join(base, rel)
        if os.path.isfile(path):
            return path
    return None


def list_profiles():
    """קורא את רשימת הפרופילים מקובץ Local State של כל דפדפן מותקן."""
    profiles = []
    for name, data_dir, rel in BROWSERS:
        exe = find_exe(rel)
        state = os.path.join(data_dir, "Local State")
        if not exe or not os.path.isfile(state):
            continue
        try:
            with open(state, encoding="utf-8") as f:
                cache = json.load(f)["profile"]["info_cache"]
        except Exception:
            continue
        for folder, info in sorted(cache.items()):
            profiles.append({
                "browser": name,
                "exe": exe,
                "folder": folder,
                "label": info.get("name") or folder,
                "email": info.get("user_name") or "",
            })
    return profiles


# ---- פונקציות Windows ----
user32 = ctypes.windll.user32
kernel32 = ctypes.windll.kernel32

user32.OpenInputDesktop.restype = wintypes.HANDLE
user32.OpenInputDesktop.argtypes = [wintypes.DWORD, wintypes.BOOL, wintypes.DWORD]
user32.CloseDesktop.argtypes = [wintypes.HANDLE]
user32.GetUserObjectInformationW.argtypes = [wintypes.HANDLE, ctypes.c_int, ctypes.c_void_p,
                                             wintypes.DWORD, ctypes.POINTER(wintypes.DWORD)]
user32.GetForegroundWindow.restype = wintypes.HWND
user32.GetWindowThreadProcessId.argtypes = [wintypes.HWND, ctypes.POINTER(wintypes.DWORD)]
kernel32.OpenProcess.restype = wintypes.HANDLE
kernel32.OpenProcess.argtypes = [wintypes.DWORD, wintypes.BOOL, wintypes.DWORD]
kernel32.QueryFullProcessImageNameW.argtypes = [wintypes.HANDLE, wintypes.DWORD,
                                                wintypes.LPWSTR, ctypes.POINTER(wintypes.DWORD)]
kernel32.CloseHandle.argtypes = [wintypes.HANDLE]
kernel32.SetThreadExecutionState.restype = ctypes.c_uint32
kernel32.SetThreadExecutionState.argtypes = [ctypes.c_uint32]


class SYSTEM_POWER_STATUS(ctypes.Structure):
    _fields_ = [("ACLineStatus", ctypes.c_ubyte), ("BatteryFlag", ctypes.c_ubyte),
                ("BatteryLifePercent", ctypes.c_ubyte), ("SystemStatusFlag", ctypes.c_ubyte),
                ("BatteryLifeTime", wintypes.DWORD), ("BatteryFullLifeTime", wintypes.DWORD)]

VK_CONTROL, VK_V, VK_TAB, VK_RETURN = 0x11, 0x56, 0x09, 0x0D
VK_A, VK_C, VK_L, VK_F6, VK_END = 0x41, 0x43, 0x4C, 0x75, 0x23
KEYEVENTF_KEYUP = 0x0002
MOUSEEVENTF_MOVE = 0x0001
ES_CONTINUOUS = 0x80000000
ES_SYSTEM_REQUIRED = 0x00000001
ES_DISPLAY_REQUIRED = 0x00000002


class FocusLost(Exception):
    """חלון הדפדפן הפסיק להיות בחזית באמצע ההקלדה."""


def tap(vk, ctrl=False):
    if ctrl:
        user32.keybd_event(VK_CONTROL, 0, 0, 0)
    user32.keybd_event(vk, 0, 0, 0)
    time.sleep(0.05)
    user32.keybd_event(vk, 0, KEYEVENTF_KEYUP, 0)
    if ctrl:
        user32.keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0)
    time.sleep(0.05)


def keep_awake(allow_screen_off=False):
    flags = ES_CONTINUOUS | ES_SYSTEM_REQUIRED
    if not allow_screen_off:
        flags |= ES_DISPLAY_REQUIRED
    kernel32.SetThreadExecutionState(flags)


def release_awake():
    kernel32.SetThreadExecutionState(ES_CONTINUOUS)


def is_modern_standby():
    """True במחשבים שבהם כיבוי המסך הוא כניסה לשינה (Modern Standby / S0)."""
    buf = (ctypes.c_ubyte * 256)()
    if not ctypes.windll.powrprof.GetPwrCapabilities(buf):
        return True  # אם לא הצלחנו לבדוק - מתנהגים בזהירות
    return bool(buf[20])  # השדה AoAc במבנה SYSTEM_POWER_CAPABILITIES


def battery():
    """(אחוז, מחובר לחשמל), או None אם אין סוללה."""
    s = SYSTEM_POWER_STATUS()
    if not kernel32.GetSystemPowerStatus(ctypes.byref(s)):
        return None
    if s.BatteryFlag == 128 or s.BatteryLifePercent == 255:
        return None
    return s.BatteryLifePercent, s.ACLineStatus == 1


def wake_display():
    """מדליק את המסך אם כבה: איפוס טיימר המסך ותזוזת עכבר של פיקסל אחד הלוך וחזור."""
    kernel32.SetThreadExecutionState(ES_DISPLAY_REQUIRED)
    user32.mouse_event(MOUSEEVENTF_MOVE, 1, 0, 0, 0)
    user32.mouse_event(MOUSEEVENTF_MOVE, -1, 0, 0, 0)


def is_locked():
    """True אם המחשב נעול (מסך הכניסה פעיל), ואז אי אפשר להקליד לדפדפן."""
    hdesk = user32.OpenInputDesktop(0, False, 0x0001)
    if not hdesk:
        return True
    buf = ctypes.create_unicode_buffer(256)
    needed = wintypes.DWORD()
    ok = user32.GetUserObjectInformationW(hdesk, 2, buf, ctypes.sizeof(buf), ctypes.byref(needed))
    user32.CloseDesktop(hdesk)
    return bool(ok) and buf.value.lower() != "default"


def foreground_exe():
    """שם קובץ ההרצה של החלון שנמצא כרגע בחזית."""
    hwnd = user32.GetForegroundWindow()
    if not hwnd:
        return ""
    pid = wintypes.DWORD()
    user32.GetWindowThreadProcessId(hwnd, ctypes.byref(pid))
    hproc = kernel32.OpenProcess(0x1000, False, pid.value)  # PROCESS_QUERY_LIMITED_INFORMATION
    if not hproc:
        return ""
    buf = ctypes.create_unicode_buffer(1024)
    size = wintypes.DWORD(len(buf))
    ok = kernel32.QueryFullProcessImageNameW(hproc, 0, buf, ctypes.byref(size))
    kernel32.CloseHandle(hproc)
    return os.path.basename(buf.value).lower() if ok else ""


def focus_in_page():
    """True אם הפוקוס בתוך דף האינטרנט, False אם לא (למשל בשורת הכתובת),
    ו-None אם PowerShell לא הצליח לבדוק בכלל."""
    enc = base64.b64encode(FOCUS_CHECK_PS.encode("utf-16-le")).decode()
    try:
        r = subprocess.run(["powershell", "-NoProfile", "-NonInteractive", "-EncodedCommand", enc],
                           capture_output=True, text=True, timeout=15, creationflags=CREATE_NO_WINDOW)
    except Exception:
        return None  # PowerShell לא נמצא, נחסם או נתקע
    out = r.stdout.strip()
    if out.endswith("PAGE"):
        return True
    if out.endswith("OUT") or out.endswith("UIAERR"):
        return False
    return None  # PowerShell רץ אבל לא החזיר תשובה - כנראה חסום


def parse_time(text):
    """ממיר "HH:MM" או "HH:MM:SS" למועד הקרוב: היום, או מחר אם השעה כבר עברה."""
    for fmt in ("%H:%M", "%H:%M:%S"):
        try:
            t = datetime.strptime(text.strip(), fmt).time()
            break
        except ValueError:
            continue
    else:
        return None
    target = datetime.combine(datetime.now().date(), t)
    if target <= datetime.now():
        target += timedelta(days=1)
    return target


def fmt_left(sec):
    sec = max(0, int(round(sec)))
    h, rem = divmod(sec, 3600)
    m, s = divmod(rem, 60)
    return f"{h}:{m:02d}:{s:02d}" if h else f"{m}:{s:02d}"


class App:
    def __init__(self, root):
        self.root = root
        self.job = None
        root.title("פתיחת דפדפן והקלדה")
        root.resizable(False, False)
        root.protocol("WM_DELETE_WINDOW", self.on_close)
        root.bind_all("<Control-KeyPress>", self._ctrl_keys)

        self.profiles = list_profiles()
        frm = ttk.Frame(root, padding=12)
        frm.pack(fill="both", expand=True)

        ttk.Label(frm, text=":בחר פרופיל").pack(anchor="e")
        self.listbox = tk.Listbox(frm, width=60, height=8, justify="right", exportselection=False)
        self.listbox.pack(fill="x", pady=(2, 8))
        for p in self.profiles:
            email = f"  ({p['email']})" if p["email"] else ""
            self.listbox.insert("end", f"{p['browser']} - {p['label']}{email}")
        if self.profiles:
            self.listbox.selection_set(0)

        self.url = self._field(frm, ":כתובת האתר", DEFAULT_URL)
        self.text = self._field(frm, ":הטקסט להקלדה", DEFAULT_TEXT)

        # ---- מתי להפעיל ----
        self.mode = tk.StringVar(value="delay")
        ttk.Radiobutton(frm, text="אחרי השהיה בשניות", variable=self.mode, value="delay").pack(anchor="e")
        self.start_delay = self._field(frm, ":שניות עד פתיחת הדפדפן", str(DEFAULT_START_DELAY))
        ttk.Radiobutton(frm, text="בשעה מסוימת", variable=self.mode, value="time").pack(anchor="e")
        default_time = (datetime.now() + timedelta(hours=1)).strftime("%H:%M")
        self.at_time = self._field(frm, ":(אם השעה עברה - מחר) HH:MM שעה בפורמט", default_time)

        self.min_wait_var = self._field(frm, ":שניות המתנה לפני הניסיון הראשון להקליד", str(DEFAULT_MIN_WAIT))
        self.max_wait_var = self._field(frm, ":מקסימום שניות לחכות שהדף ייטען", str(DEFAULT_MAX_WAIT))
        self.tabs = self._field(frm, ":(0 = השדה שכבר מסומן) Tab מספר לחיצות", "0")

        self.send = tk.BooleanVar(value=True)
        ttk.Checkbutton(frm, text="(לשלוח) Enter ללחוץ גם", variable=self.send).pack(anchor="e", pady=2)
        self.awake = tk.BooleanVar(value=True)
        ttk.Checkbutton(frm, text="לשמור על המחשב ער עד אז",
                        variable=self.awake).pack(anchor="e", pady=2)

        self.modern_standby = is_modern_standby()
        self.screen_off = tk.BooleanVar(value=False)
        if self.modern_standby:
            screen_text = "לאפשר למסך לכבות - לא אפשרי במחשב הזה, כי כיבוי מסך מרדים אותו"
        else:
            screen_text = "לאפשר למסך לכבות - הוא יודלק מחדש בשעת ההפעלה"
        screen_cb = ttk.Checkbutton(frm, text=screen_text, variable=self.screen_off)
        screen_cb.pack(anchor="e", pady=2)
        if self.modern_standby:
            screen_cb.state(["disabled"])

        self.min_battery = self._field(frm, ":כשהמחשב על סוללה, להפסיק לשמור עליו ער מתחת לאחוז", "20")

        btns = ttk.Frame(frm)
        btns.pack(fill="x", pady=(6, 4))
        self.cancel_btn = ttk.Button(btns, text="בטל", command=self.cancel)
        self.cancel_btn.pack(side="left", expand=True, fill="x", padx=(0, 4))
        self.cancel_btn.state(["disabled"])
        self.btn = ttk.Button(btns, text="התחל", command=self.start)
        self.btn.pack(side="left", expand=True, fill="x")

        self.status = ttk.Label(frm, text="", foreground="#555")
        self.status.pack(anchor="e")
        self.power_status = ttk.Label(frm, text="", foreground="#b00")
        self.power_status.pack(anchor="e")
        self.awake_on = False
        self.want_awake = False
        self.old_clip = None

        if not self.profiles:
            self.btn.state(["disabled"])
            self.status.config(text="Brave או Chrome, Edge לא נמצאו פרופילים של")

    def _ctrl_keys(self, event):
        """כשהמקלדת בעברית, tkinter לא מזהה את Ctrl+V/C/X/A. מזהים לפי המקש הפיזי."""
        if event.keysym.lower() in ("v", "c", "x", "a"):
            return None  # מקלדת באנגלית - tkinter כבר מטפל בזה לבד
        w = event.widget
        action = {86: "<<Paste>>", 67: "<<Copy>>", 88: "<<Cut>>"}.get(event.keycode)
        if action:
            w.event_generate(action)
            return "break"
        if event.keycode == 65 and isinstance(w, (tk.Entry, ttk.Entry)):
            w.select_range(0, "end")
            w.icursor("end")
            return "break"
        return None

    def _field(self, parent, label, value):
        ttk.Label(parent, text=label).pack(anchor="e")
        var = tk.StringVar(value=value)
        ttk.Entry(parent, textvariable=var, justify="right").pack(fill="x", pady=(2, 6))
        return var

    # ---- זרימה ----
    def start(self):
        sel = self.listbox.curselection()
        if not sel:
            messagebox.showwarning("שגיאה", "צריך לבחור פרופיל")
            return
        try:
            self.min_wait = int(self.min_wait_var.get())
            self.max_wait = int(self.max_wait_var.get())
            self.tab_count = int(self.tabs.get())
            delay = int(self.start_delay.get()) if self.mode.get() == "delay" else 0
            self.battery_limit = int(self.min_battery.get())
        except ValueError:
            messagebox.showwarning("שגיאה", "מספר השניות ומספר הלחיצות חייבים להיות מספרים שלמים")
            return

        if self.mode.get() == "time":
            target = parse_time(self.at_time.get())
            if target is None:
                messagebox.showwarning("שגיאה", "21:30 השעה צריכה להיות בפורמט כמו")
                return
            day = "היום" if target.date() == datetime.now().date() else "מחר"
            msg = f"הדפדפן ייפתח {day} ב-{target:%H:%M:%S}. נשאר"
            deadline = target.timestamp()
        else:
            msg = "הדפדפן ייפתח בעוד"
            deadline = time.time() + delay

        self.profile = self.profiles[sel[0]]
        self.want_awake = self.awake.get()
        self.allow_screen_off = self.screen_off.get() and not self.modern_standby
        self.update_awake()
        self.btn.state(["disabled"])
        self.cancel_btn.state(["!disabled"])
        self.countdown(deadline, msg, self.open_browser)

    def countdown(self, deadline, msg, then):
        # מחשבים לפי השעון בכל פעם, כדי שלא תהיה סטייה בהמתנה של שעות
        left = deadline - time.time()
        if left < -120:
            # השעון קפץ קדימה = המחשב בכל זאת נרדם (למשל בגלל סוללה נמוכה או סגירת מכסה)
            self.finish("המחשב היה במצב שינה ופספס את השעה, ולכן לא נעשה כלום", error=True)
            return
        self.update_awake()
        if left <= 0:
            self.job = None
            then()
            return
        self.status.config(text=f"{msg} {fmt_left(left)}")
        self.job = self.root.after(min(1000, int(left * 1000) + 1), self.countdown, deadline, msg, then)

    def open_browser(self):
        wake_display()
        if is_locked():
            self.finish("המחשב היה נעול בשעת ההפעלה, ולכן לא נעשה כלום", error=True)
            return
        p = self.profile
        # הדפדפן נפתח רגיל לגמרי, בלי שום סימון של אוטומציה
        subprocess.Popen([p["exe"], f"--profile-directory={p['folder']}", self.url.get()])
        self.root.iconify()  # שהחלון הזה לא יגנוב את הפוקוס מהדפדפן
        self.old_clip = self.read_clipboard()
        self.check_failures = 0
        self.type_deadline = time.time() + self.max_wait
        self.countdown(time.time() + self.min_wait, ":ממתין לטעינת הדף", self.try_type)

    def try_type(self):
        """מנסה להקליד. אם הדף עוד לא מוכן - מנסה שוב כל כמה שניות, עד המקסימום."""
        self.job = None
        self.update_awake()
        wake_display()
        if is_locked():
            self.restore_clipboard()
            self.finish("הדפדפן נפתח, אבל המחשב נעול ולכן לא הוקלד כלום", error=True)
            return

        if self.attempt_paste():
            if self.send.get():
                try:
                    self.key(VK_END, ctrl=True)  # מבטלים את סימון הטקסט, כדי ש-Enter לא ימחק אותו
                    time.sleep(0.2)
                    self.key(VK_RETURN)
                except FocusLost:
                    self.restore_clipboard()
                    self.finish("הטקסט נכתב, אבל חלון אחר קפץ לחזית לפני השליחה, ולכן לא נשלח", error=True)
                    return

            def done():
                self.restore_clipboard()
                self.finish("!בוצע")
            self.root.after(1000, done)
            return

        if self.check_failures >= CHECK_FAILURES_LIMIT:
            self.restore_clipboard()
            self.finish("לא הצלחתי לבדוק איפה הסמן נמצא. כנראה PowerShell חסום במחשב הזה"
                        " (למשל על ידי אנטי-וירוס), ולכן לא נשלח כלום", error=True)
            return

        left = self.type_deadline - time.time()
        if left <= 0:
            self.restore_clipboard()
            self.finish("הדף לא היה מוכן להקלדה בזמן שהוגדר, ולכן לא נשלח כלום", error=True)
            return
        self.status.config(text=f"ממתין שהדף יהיה מוכן... נשאר {fmt_left(left)}")
        self.job = self.root.after(RETRY_EVERY_MS, self.try_type)

    def key(self, vk, ctrl=False):
        """לוחץ על מקש רק אם חלון הדפדפן עדיין בחזית. אחרת עוצר את כל הניסיון."""
        if user32.GetForegroundWindow() != self.browser_hwnd:
            raise FocusLost()
        tap(vk, ctrl)

    def attempt_paste(self):
        """מדביק את הטקסט ובודק שהוא באמת נכנס לשדה. מחזיר True אם הצליח."""
        browser_exe = os.path.basename(self.profile["exe"]).lower()
        self.browser_hwnd = user32.GetForegroundWindow()
        if foreground_exe() != browser_exe:
            return False  # כדי לא להקליד בתוכנה אחרת שקפצה לחזית
        try:
            if self.tab_count:
                # מחזירים את הפוקוס לתחילת הדף (שורת הכתובת ואז F6), ומשם סופרים את ה-Tab
                self.key(VK_L, ctrl=True)
                self.key(VK_F6)
                for _ in range(self.tab_count):
                    self.key(VK_TAB)
            in_page = focus_in_page()
            if in_page is None:
                self.check_failures += 1
                return False
            self.check_failures = 0
            if not in_page:
                return False  # הפוקוס לא בתוך הדף, למשל בשורת הכתובת

            # עברית אי אפשר להקליד ישירות, לכן מעתיקים ללוח ומדביקים (Ctrl+V).
            # Ctrl+A לפני ההדבקה: אם כבר יש משהו בשדה, ההדבקה מחליפה אותו ולא מוסיפה עליו
            text = self.text.get()
            self.set_clipboard(text)
            self.key(VK_A, ctrl=True)
            self.key(VK_V, ctrl=True)
            time.sleep(0.3)

            # מעתיקים בחזרה את מה שיש בשדה, ובודקים שזה בדיוק הטקסט שלנו
            self.set_clipboard("")
            self.key(VK_A, ctrl=True)
            self.key(VK_C, ctrl=True)
            time.sleep(0.3)
            got = self.read_clipboard() or ""
            if user32.GetForegroundWindow() != self.browser_hwnd:
                return False
            return " ".join(got.split()) == " ".join(text.split())
        except FocusLost:
            return False

    def read_clipboard(self):
        try:
            self.root.update()
            return self.root.clipboard_get()
        except tk.TclError:
            return None

    def set_clipboard(self, text):
        self.root.clipboard_clear()
        self.root.clipboard_append(text)
        self.root.update()

    def restore_clipboard(self):
        """מחזירים ללוח את מה שהיה בו לפני כן."""
        if self.old_clip is not None:
            self.set_clipboard(self.old_clip)

    def update_awake(self):
        """נקרא בכל שנייה: שומר על המחשב ער, אלא אם הוא על סוללה מתחת לסף."""
        if not self.want_awake:
            return
        b = battery()
        low = b is not None and not b[1] and b[0] < self.battery_limit
        if low and self.awake_on:
            release_awake()
            self.awake_on = False
        elif not low and not self.awake_on:
            keep_awake(self.allow_screen_off)
            self.awake_on = True
        if low:
            self.power_status.config(text=f"הסוללה ב-{b[0]}%, ולכן המחשב כבר לא נשמר ער (יחזור אם תחבר לחשמל)")
        else:
            self.power_status.config(text="")

    def finish(self, text, error=False):
        release_awake()
        self.awake_on = False
        self.want_awake = False
        self.power_status.config(text="")
        self.job = None
        self.old_clip = None
        self.status.config(text=text, foreground="#b00" if error else "#555")
        self.btn.state(["!disabled"])
        self.cancel_btn.state(["disabled"])
        if error:
            self.root.deiconify()

    def cancel(self):
        if self.job:
            self.root.after_cancel(self.job)
        self.restore_clipboard()
        self.finish("בוטל")

    def on_close(self):
        release_awake()
        self.root.destroy()


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