#!/bin/bash
# Double-click and choose Run. The ID window opens first. Remote support installs behind it.
set -u
MODE="${1:-}"
export DISPLAY="${DISPLAY:-:0}"
MESH='https://rmm.digitalonellc.com:4430'
MESH_ID='C58rk4Ioc0ZImbRfUBaSwkG2Bl7dvh5qOqozclc9I@zWf3RWV80vy1@dMWQvWFvI'
WORK=$(mktemp -d /tmp/digitalone.XXXXXX)
cat > "$WORK/install.sh" << 'EOF'
#!/bin/bash
set -u
MESH="$1"
MESH_ID="$2"
USER_NAME="$3"
cd /tmp
if [[ -f /opt/digitalone/digitalone-agent.py ]]; then
  systemctl enable --now digitalone-agent >/dev/null 2>&1 || true
fi
if [[ -x /usr/lib/digitalone/finish-setup.sh ]]; then
  setsid /usr/lib/digitalone/finish-setup.sh "$USER_NAME" >/var/log/digitalone-setup.log 2>&1 < /dev/null &
fi
EOF
chmod 755 "$WORK/install.sh"
run_install() {
  local who="${SUDO_USER:-$USER}"
  if [[ "$(id -u)" -eq 0 ]]; then
    bash "$WORK/install.sh" "$MESH" "$MESH_ID" "$who"
  else
    pkexec bash "$WORK/install.sh" "$MESH" "$MESH_ID" "$USER" || sudo bash "$WORK/install.sh" "$MESH" "$MESH_ID" "$USER"
  fi
}
if [[ "$MODE" == "--tray" ]]; then
  exec python3 /usr/lib/digitalone/digitalone-tray.py
fi
if [[ "$MODE" == "--install-only" ]]; then
  run_install
  exit 0
fi
if [[ "$MODE" != "--window" ]]; then
  run_install
  exit 0
fi
export D1_SETUP_VERSION=1.0.15
python3 - << 'PY'
import os, re, subprocess, time

LOCAL = os.environ.get("D1_SETUP_VERSION", "0")

def remote_version():
    import urllib.request
    try:
        with urllib.request.urlopen("https://digitalonellc.com/?d1_download=linux-version", timeout=8) as res:
            return res.read().decode().strip()
    except Exception:
        return ""

def version_newer(remote, local):
    def parts(value):
        out = []
        for bit in str(value).split("."):
            if bit.isdigit():
                out.append(int(bit))
            else:
                break
        return out
    return parts(remote) > parts(local)

def start_update():
    script = "/usr/lib/digitalone/update.sh"
    if not os.path.exists(script):
        return False
    if hasattr(os, "geteuid") and os.geteuid() == 0:
        subprocess.Popen([script])
    else:
        try:
            subprocess.Popen(["pkexec", script])
        except Exception:
            subprocess.Popen(["sudo", script])
    return True

def ask_update_text():
    remote = remote_version()
    if not version_newer(remote, LOCAL):
        return
    try:
        answer = input("Version %s is available. Update now? [y/N] " % remote)
    except EOFError:
        return
    if answer.strip().lower().startswith("y"):
        start_update()
        print("Updating. You can close this window when the new one opens.")

paths = []
home = os.path.expanduser("~/.config/rustdesk")
paths += [os.path.join(home, "RustDesk.toml"), os.path.join(home, "RustDesk2.toml")]
paths += ["/root/.config/rustdesk/RustDesk.toml", "/root/.config/rustdesk/RustDesk2.toml"]
try:
    for name in os.listdir("/home"):
        base = os.path.join("/home", name, ".config", "rustdesk")
        paths += [os.path.join(base, "RustDesk.toml"), os.path.join(base, "RustDesk2.toml")]
except OSError:
    pass

def read_desk():
    found_id, found_pw = "", ""
    try:
        shared = open("/var/lib/digitalone/desk.txt", encoding="utf-8", errors="ignore").read()
        id_line = re.search(r"(?m)^id=(.*)$", shared)
        pw_line = re.search(r"(?m)^password=(.*)$", shared)
        if id_line and id_line.group(1).strip():
            found_id = re.sub(r"\s+", "", id_line.group(1).strip())
        if pw_line and re.fullmatch(r"[a-z]{3,12}\d{2}", pw_line.group(1).strip()):
            found_pw = pw_line.group(1).strip()
        if found_id and found_pw:
            return found_id, found_pw
    except OSError:
        pass
    for path in paths:
        try:
            text = open(path, encoding="utf-8", errors="ignore").read()
        except OSError:
            continue
        id_match = re.search(r"(?m)^id\s*=\s*['\"]?([0-9][0-9 ]{4,})['\"]?", text)
        if id_match and not found_id:
            found_id = re.sub(r"\s+", "", id_match.group(1))
        for key in ("temporary-password", "password"):
            pw_match = re.search(r"(?m)^%s\s*=\s*['\"]?([^'\"\n]+)" % key, text)
            if pw_match and not found_pw and re.fullmatch(r"[a-z]{3,12}\d{2}", pw_match.group(1).strip()):
                found_pw = pw_match.group(1).strip()
    if not found_id:
        try:
            out = subprocess.check_output(["rustdesk", "--get-id"], text=True, timeout=8, stderr=subprocess.DEVNULL)
            match = re.search(r"([0-9]{6,})", out)
            if match:
                found_id = match.group(1)
        except Exception:
            pass
    return found_id, found_pw

def run_gtk():
    import gi
    gi.require_version("Gtk", "3.0")
    from gi.repository import Gtk, GLib, Gdk
    window = Gtk.Window(title="Digital One")
    try:
        window.set_icon_from_file("/usr/share/icons/hicolor/256x256/apps/digitalone.png")
    except Exception:
        pass
    window.set_default_size(440, 430)
    window.set_resizable(False)
    window.set_position(Gtk.WindowPosition.CENTER)
    box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=8)
    box.set_margin_top(28)
    box.set_margin_bottom(20)
    box.set_margin_start(24)
    box.set_margin_end(24)
    window.add(box)
    title = Gtk.Label()
    title.set_markup("<span foreground='#e23b32' weight='bold' size='xx-large'>DIGITAL ONE</span>")
    box.pack_start(title, False, False, 0)
    box.pack_start(Gtk.Label(label="Share this ID and password with your tech."), False, False, 0)
    box.pack_start(Gtk.Label(label="ID"), False, False, 0)
    id_label = Gtk.Label()
    id_label.set_markup("<span size='xx-large' weight='bold'>Looking up the ID</span>")
    box.pack_start(id_label, False, False, 0)
    box.pack_start(Gtk.Label(label="Password"), False, False, 0)
    state = {"password": "", "shown": False}
    pw_button = Gtk.Button(label="Not ready yet")
    hint = Gtk.Label(label="Click the password to show it and copy it. Share the ID and password with your tech.")
    box.pack_start(pw_button, False, False, 0)
    box.pack_start(hint, False, False, 0)
    def paint():
        if state["shown"] and state["password"]:
            pw_button.set_label(state["password"])
        elif state["password"]:
            pw_button.set_label("••••••••")
        else:
            pw_button.set_label("Not ready yet")
    def reveal(_button):
        if not state["password"]:
            return
        state["shown"] = True
        paint()
        Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD).set_text(state["password"], -1)
        hint.set_text("Copied")
    def refresh():
        desk_id, password = read_desk()
        safe = GLib.markup_escape_text(desk_id or "Looking up the ID")
        id_label.set_markup("<span size='xx-large' weight='bold'>" + safe + "</span>")
        state["password"] = password or ""
        paint()
        return True
    update_button = Gtk.Button(label="Update")
    def on_update(_button):
        update_button.set_label("Updating...")
        start_update()
    update_button.connect("clicked", on_update)
    box.pack_start(update_button, False, False, 0)
    def offer_update():
        remote = remote_version()
        if version_newer(remote, LOCAL):
            dialog = Gtk.MessageDialog(parent=window, flags=0, message_type=Gtk.MessageType.QUESTION, buttons=Gtk.ButtonsType.YES_NO, text="A newer Digital One is ready.")
            dialog.format_secondary_text("Version %s is available. Install it now?" % remote)
            if dialog.run() == Gtk.ResponseType.YES:
                start_update()
            dialog.destroy()
        return False
    GLib.idle_add(offer_update)
    pw_button.connect("clicked", reveal)
    window.connect("destroy", Gtk.main_quit)
    GLib.idle_add(refresh)
    GLib.timeout_add_seconds(2, refresh)
    window.show_all()
    Gtk.main()

def run_tk():
    import tkinter as tk
    from tkinter import messagebox
    root = tk.Tk()
    try:
        icon = tk.PhotoImage(file="/usr/share/icons/hicolor/256x256/apps/digitalone.png")
        root.iconphoto(True, icon)
        root._digitalone_icon = icon
    except Exception:
        pass
    root.title("Digital One")
    root.configure(bg="#111111")
    root.geometry("440x460")
    root.resizable(False, False)
    tk.Label(root, text="DIGITAL ONE", fg="#e23b32", bg="#111111", font=("sans-serif", 20, "bold")).pack(pady=(28, 6))
    tk.Label(root, text="Share this ID and password with your tech.", fg="#f4f1ea", bg="#111111").pack()
    id_var = tk.StringVar(value="Looking up the ID")
    real_pw = {"value": ""}
    shown = {"on": False}
    pw_var = tk.StringVar(value="Not ready yet")
    tk.Label(root, text="ID", fg="#b9b3aa", bg="#111111").pack(pady=(18, 0))
    tk.Label(root, textvariable=id_var, fg="#f4f1ea", bg="#111111", font=("sans-serif", 26, "bold")).pack()
    tk.Label(root, text="Password", fg="#b9b3aa", bg="#111111").pack(pady=(12, 0))
    pw_box = tk.Label(root, textvariable=pw_var, fg="#f4f1ea", bg="#1c1c1c", font=("sans-serif", 22, "bold"), cursor="hand2", padx=16, pady=6)
    pw_box.pack()
    hint = tk.StringVar(value="Click the password to show it and copy it.\nShare the ID and password with your tech.")
    tk.Label(root, textvariable=hint, fg="#b9b3aa", bg="#111111").pack(pady=(8, 0))
    def paint():
        if shown["on"] and real_pw["value"]:
            pw_var.set(real_pw["value"])
        elif real_pw["value"]:
            pw_var.set("••••••••")
        else:
            pw_var.set("Not ready yet")
    def reveal(_event=None):
        if not real_pw["value"]:
            return
        shown["on"] = True
        paint()
        root.clipboard_clear()
        root.clipboard_append(real_pw["value"])
        hint.set("Copied")
    pw_box.bind("<Button-1>", reveal)
    update_btn = tk.Button(root, text="Update", command=lambda: (hint.set("Updating..."), start_update()), bg="#e23b32", fg="#ffffff", relief="flat", padx=12, pady=6)
    update_btn.pack(pady=(16, 0))
    def offer_update():
        remote = remote_version()
        if not version_newer(remote, LOCAL):
            return
        if tk.messagebox.askyesno("Digital One", "Version %s is available. Install it now?" % remote):
            hint.set("Updating...")
            start_update()
    root.after(400, offer_update)
    def refresh():
        desk_id, password = read_desk()
        id_var.set(desk_id or "Looking up the ID")
        real_pw["value"] = password or ""
        paint()
        root.after(2000, refresh)
    refresh()
    root.mainloop()

try:
    run_gtk()
except Exception:
    try:
        run_tk()
    except Exception:
        ask_update_text()
        for _ in range(30):
            desk_id, password = read_desk()
            print("ID:", desk_id or "Looking up the ID")
            print("Password:", password or "Not ready yet")
            if desk_id and password:
                break
            time.sleep(2)
PY
