// ARGUS Beta — terminal.enhance.js (Faz A)
// Touch-friendly layer on top of the xterm bundle. Loaded AFTER terminal.bundle.js,
// reaches the terminal via window.__argusTerm / __argusSend / __argusKeyboard which
// the bundle exposes (one-line expose patch in terminal.bundle.js). The minified
// bundle itself is left untouched beyond that single export line.
//
// Adds, for mobile (Android WebView) use:
//   1) touch-drag scroll with momentum (drag the terminal body to scroll scrollback)
//   2) a thick, easy-to-grab scrollbar
//   3) long-press context menu: Yapıştır / Kopyala / Tümünü Kopyala
//   4) auto-copy to clipboard when a selection is made
(function () {
  "use strict";

  // ---- keyboard-scroll fix (root cause: the WebView scrolls the whole document
  // to reveal the focused xterm helper-textarea — which sits at the cursor row deep
  // in the screen — when the soft keyboard opens, snapping the page to the bottom).
  // This is a FIXED SHELL: header pinned top, terminal in the middle, key bar above
  // the keyboard. The document must NEVER scroll vertically; the terminal owns its
  // own scrollback. So: (a) make every element focus default to preventScroll, and
  // (b) snap any stray vertical document scroll back to 0. Pairs with Android
  // windowSoftInputMode=adjustNothing so the OS no longer pans to the focused field. ----
  (function patchFocus() {
    try {
      var P = HTMLElement.prototype, of = P.focus;
      if (of && !of.__argusPatched) {
        P.focus = function (opts) {
          // build a fresh options object — never mutate a caller-supplied (possibly
          // frozen) one. Explicit {preventScroll:false} from a caller still wins.
          var o = { preventScroll: true };
          if (opts && typeof opts === "object") { for (var k in opts) o[k] = opts[k]; }
          return of.call(this, o);
        };
        P.focus.__argusPatched = true;
      }
    } catch (_) {}
  })();

  // Mirror the visual viewport into --vvh/--vvt so full-screen fixed overlays
  // (#launcher, #dc-sheet, #argus-chat) keep their bottom content above the soft
  // keyboard. Runs immediately (not gated on the terminal) since the launcher/chat
  // can appear before xterm is ready. With adjustNothing the IME shrinks only the
  // visual viewport, so position:fixed;inset:0 alone would hide the chat input.
  function setupViewportVars() {
    if (window.__argusVVVars) return;
    window.__argusVVVars = true;
    var de = document.documentElement;
    function update() {
      var vv = window.visualViewport;
      if (vv) { de.style.setProperty("--vvh", vv.height + "px"); de.style.setProperty("--vvt", vv.offsetTop + "px"); }
      else { de.style.setProperty("--vvh", "100%"); de.style.setProperty("--vvt", "0px"); }
    }
    update();
    if (window.visualViewport) {
      window.visualViewport.addEventListener("resize", update);
      window.visualViewport.addEventListener("scroll", update);
    }
    window.addEventListener("orientationchange", update);
  }
  setupViewportVars();

  function setupScrollPin() {
    if (window.__argusScrollPinned) return;
    window.__argusScrollPinned = true;
    var queued = false;
    function pinTop() {
      if (queued) return; queued = true;
      requestAnimationFrame(function () {
        queued = false;
        if (window.scrollY) window.scrollTo(0, 0);          // window/layout scroll only —
        var se = document.scrollingElement || document.documentElement;
        if (se && se.scrollTop) se.scrollTop = 0;             // NEVER the .xterm-viewport scrollback
      });
    }
    window.addEventListener("scroll", pinTop, { passive: true, capture: true });
    document.addEventListener("focusin", pinTop, true);
    if (window.visualViewport) {
      window.visualViewport.addEventListener("scroll", pinTop);
      window.visualViewport.addEventListener("resize", pinTop);
    }
  }

  // Re-skin the terminal canvas to the Obsidian DC brand (the bundle ships a teal
  // #071016 bg + green cursor; we own __argusTerm so we retheme at runtime — no
  // bundle edit). ANSI ramp is a calm, blue-aligned set readable on #0b0b0c.
  function applyTheme(term) {
    try {
      var theme = {
        background: "#0b0b0c", foreground: "#e6e9ec",
        cursor: "#0a84ff", cursorAccent: "#0b0b0c",
        selectionBackground: "rgba(10,132,255,0.30)",
        black: "#15161a", red: "#f7768e", green: "#9ece6a", yellow: "#e0af68",
        blue: "#7aa2f7", magenta: "#bb9af7", cyan: "#7dcfff", white: "#c0caf5",
        brightBlack: "#41454c", brightRed: "#ff8aa0", brightGreen: "#b9e07f", brightYellow: "#f0c785",
        brightBlue: "#93b5ff", brightMagenta: "#cbb1ff", brightCyan: "#9ce0ff", brightWhite: "#f4f6f6"
      };
      if (term.options) term.options.theme = theme;          // xterm 5.x
      else if (term.setOption) term.setOption("theme", theme); // older
      if (term.refresh && typeof term.rows === "number") term.refresh(0, term.rows - 1);
    } catch (_) {}
  }

  function onReady(term) {
    var el = term && term.element;
    if (!el) return;
    var vp = el.querySelector(".xterm-viewport");
    if (!vp) return;
    if (el.__argusEnhanced) return; // idempotent
    el.__argusEnhanced = true;

    injectCSS();
    applyTheme(term);
    setupScrollPin();

    // ---- touch-drag scroll (+ momentum) and long-press menu ----
    // NOTE: this xterm build does NOT make .xterm-viewport natively scrollable
    // (scrollHeight === clientHeight), so vp.scrollTop is a no-op. We scroll the
    // terminal programmatically via term.scrollLines(n): n<0 = back in history.
    // We accumulate pixel drag and convert to whole lines using the cell height.
    var active = false, lastY = 0, accum = 0, vyPx = 0, raf = 0, cell = 22,
        startX = 0, startY = 0, moved = false, longTimer = 0;

    function cellPx() { return (vp.clientHeight / (term.rows || 35)) || 22; }
    function scrollByAccum() {
      var lines = accum / cell | 0; // truncate toward zero
      if (lines !== 0) { term.scrollLines(lines); accum -= lines * cell; }
    }

    el.addEventListener("touchstart", function (e) {
      if (e.touches.length !== 1) return;
      active = true; moved = false; accum = 0; vyPx = 0; cell = cellPx();
      startX = e.touches[0].clientX;
      startY = lastY = e.touches[0].clientY;
      cancelAnimationFrame(raf);
      clearTimeout(longTimer);
      longTimer = setTimeout(function () { if (!moved && active) showMenu(startX, startY); }, 500);
    }, { passive: false });

    el.addEventListener("touchmove", function (e) {
      if (!active || e.touches.length !== 1) return;
      var y = e.touches[0].clientY, x = e.touches[0].clientX;
      if (!moved && (Math.abs(y - startY) > 8 || Math.abs(x - startX) > 8)) {
        moved = true; clearTimeout(longTimer);
      }
      if (moved) {
        var delta = lastY - y;            // finger down (y grows) => delta<0 => scroll back
        accum += delta;
        vyPx = 0.6 * vyPx + 0.4 * delta;  // smoothed velocity for momentum
        lastY = y;
        scrollByAccum();
        e.preventDefault();               // own the gesture once it's a drag
      }
    }, { passive: false });

    function endTouch() {
      if (!active) return;
      active = false; clearTimeout(longTimer);
      if (!moved) return;
      var step = function () {
        if (Math.abs(vyPx) < 0.5) return;
        accum += vyPx; vyPx *= 0.92;
        scrollByAccum();
        raf = requestAnimationFrame(step);
      };
      step();
    }
    el.addEventListener("touchend", endTouch, { passive: false });
    el.addEventListener("touchcancel", endTouch, { passive: false });

    // ---- auto-copy on selection ----
    if (term.onSelectionChange) {
      term.onSelectionChange(function () {
        if (term.hasSelection && term.hasSelection()) {
          var sel = term.getSelection();
          if (sel) copyText(sel, true);
        }
      });
    }

    // ---- native bubble/notification on terminal bell (both modes) ----
    if (term.onBell) {
      term.onBell(function () { notifyNative("Terminal", "İşlem tamamlandı / dikkat"); });
    }
  }

  // Bridge to the Android host (Faz C). No-op in a plain browser/PC. Only fires when
  // the app is backgrounded (native also re-checks foreground before posting).
  function notifyNative(title, body) {
    try {
      if (document.hidden && window.AndroidBridge && typeof window.AndroidBridge.notify === "function") {
        window.AndroidBridge.notify(title || "Device Connect", body || "");
      }
    } catch (_) {}
  }

  // ---------- clipboard ----------
  function copyText(text, quiet) {
    if (!text) return;
    var done = function () { toast(quiet ? "Kopyalandı" : "Kopyalandı (" + text.length + ")"); };
    try {
      if (navigator.clipboard && navigator.clipboard.writeText) {
        navigator.clipboard.writeText(text).then(done, function () { legacyCopy(text); });
        return;
      }
    } catch (_) {}
    legacyCopy(text);
  }
  function legacyCopy(text) {
    var ta = document.createElement("textarea");
    ta.value = text; ta.style.position = "fixed"; ta.style.left = "-9999px";
    document.body.appendChild(ta); ta.focus(); ta.select();
    try { document.execCommand("copy"); toast("Kopyalandı"); } catch (_) {}
    document.body.removeChild(ta);
  }
  function pasteText() {
    var send = window.__argusSend;
    try {
      if (navigator.clipboard && navigator.clipboard.readText) {
        navigator.clipboard.readText().then(function (t) {
          if (t && send) { send({ type: "input", data: t }); toast("Yapıştırıldı"); }
          else if (!t) toast("Pano boş");
        }, function () { kbdPasteFallback(); });
        return;
      }
    } catch (_) {}
    kbdPasteFallback();
  }
  function kbdPasteFallback() {
    var kbd = window.__argusKeyboard;
    if (kbd && typeof kbd.paste === "function") { kbd.paste(); }
    else toast("Pano okunamadı");
  }
  // ---------- file/photo upload (phone -> agent host disk) ----------
  function authToken() {
    return window.ARGUS_TOKEN || new URLSearchParams(location.search).get("t") || "";
  }
  // uploadFile(onPath): opens the native picker, uploads to the agent, then either
  // calls onPath(path) (chat mode) or types the path into the terminal (default).
  function uploadFile(onPath) {
    var inp = document.createElement("input");
    inp.type = "file";
    inp.accept = "image/*,application/pdf,text/*,*/*";
    inp.style.position = "fixed"; inp.style.left = "-9999px";
    document.body.appendChild(inp);
    inp.addEventListener("change", function () {
      var f = inp.files && inp.files[0];
      if (!f) { inp.remove(); return; }
      toast("Yükleniyor: " + f.name);
      var fd = new FormData();
      fd.append("file", f, f.name || "upload");
      fetch("/api/upload", { method: "POST", headers: { Authorization: "Bearer " + authToken() }, body: fd })
        .then(function (r) { return r.ok ? r.json() : r.text().then(function (t) { throw new Error(t); }); })
        .then(function (j) {
          if (typeof onPath === "function") { onPath(j.path); }
          else if (window.__argusSend && j.path) { window.__argusSend({ type: "input", data: j.path + " " }); }
          toast("Yüklendi → yol eklendi");
        })
        .catch(function () { toast("Yükleme hatası"); })
        .finally(function () { inp.remove(); });
    });
    inp.click();
  }
  window.ArgusEnhance = { uploadFile: uploadFile, copyText: copyText, notifyNative: notifyNative };

  function copyAll() {
    var term = window.__argusTerm; if (!term) return;
    try {
      var buf = term.buffer.active, lines = [];
      for (var i = 0; i < buf.length; i++) {
        var ln = buf.getLine(i);
        lines.push(ln ? ln.translateToString(true) : "");
      }
      while (lines.length && !lines[lines.length - 1].trim()) lines.pop();
      copyText(lines.join("\n"));
    } catch (_) {}
  }

  // ---------- long-press context menu ----------
  var menuEl = null;
  function showMenu(x, y) {
    hideMenu();
    var term = window.__argusTerm;
    var hasSel = term && term.hasSelection && term.hasSelection();
    menuEl = document.createElement("div");
    menuEl.className = "argus-menu";
    var items = [["Yapıştır", pasteText]];
    if (hasSel) items.push(["Kopyala", function () { copyText(term.getSelection()); }]);
    items.push(["Tümünü Kopyala", copyAll]);
    items.push(["Foto / Dosya Yükle", uploadFile]);
    items.forEach(function (it) {
      var b = document.createElement("button");
      b.textContent = it[0]; b.className = "argus-menu-item";
      b.addEventListener("click", function (ev) { ev.stopPropagation(); hideMenu(); it[1](); });
      menuEl.appendChild(b);
    });
    document.body.appendChild(menuEl);
    var r = menuEl.getBoundingClientRect();
    var px = Math.min(Math.max(8, x - r.width / 2), window.innerWidth - r.width - 8);
    var py = Math.min(Math.max(48, y - r.height - 12), window.innerHeight - r.height - 8);
    menuEl.style.left = px + "px"; menuEl.style.top = py + "px";
    setTimeout(function () {
      document.addEventListener("touchstart", hideMenuOnce, true);
      document.addEventListener("mousedown", hideMenuOnce, true);
    }, 0);
    if (navigator.vibrate) { try { navigator.vibrate(12); } catch (_) {} }
  }
  function hideMenuOnce(e) { if (menuEl && !menuEl.contains(e.target)) hideMenu(); }
  function hideMenu() {
    if (!menuEl) return;
    menuEl.remove(); menuEl = null;
    document.removeEventListener("touchstart", hideMenuOnce, true);
    document.removeEventListener("mousedown", hideMenuOnce, true);
  }

  // ---------- toast ----------
  var toastEl = null, toastT = 0;
  function toast(msg) {
    if (!toastEl) { toastEl = document.createElement("div"); toastEl.className = "argus-toast"; document.body.appendChild(toastEl); }
    toastEl.textContent = msg; toastEl.classList.add("show");
    clearTimeout(toastT);
    toastT = setTimeout(function () { toastEl.classList.remove("show"); }, 1400);
  }

  function injectCSS() {
    if (document.getElementById("argus-enhance-css")) return;
    var s = document.createElement("style"); s.id = "argus-enhance-css";
    s.textContent = [
      ".xterm-viewport::-webkit-scrollbar{width:12px}",
      ".xterm-viewport::-webkit-scrollbar-track{background:transparent}",
      ".xterm-viewport::-webkit-scrollbar-thumb{background:var(--scroll-thumb);border-radius:var(--r-pill);border:3px solid var(--bg);min-height:48px}",
      ".xterm-viewport::-webkit-scrollbar-thumb:active{background:var(--scroll-thumb-active)}",
      ".argus-toast{position:fixed;left:50%;bottom:calc(96px + var(--sab));transform:translateX(-50%) translateY(8px);background:var(--surface-2);color:var(--text);border:1px solid var(--border-strong);border-radius:var(--r-pill);padding:var(--sp-2) var(--sp-4);font:var(--fw-semibold) var(--fs-300)/1 var(--font-ui);z-index:1000;opacity:0;pointer-events:none;transition:opacity .15s ease,transform .15s ease;box-shadow:var(--shadow-2)}",
      ".argus-toast.show{opacity:1;transform:translateX(-50%) translateY(0)}",
      ".argus-menu{position:fixed;z-index:1001;background:var(--surface-1);border:1px solid var(--border-strong);border-radius:var(--r-md);padding:var(--sp-1);display:flex;flex-direction:column;gap:2px;box-shadow:var(--shadow-3);min-width:180px}",
      ".argus-menu-item{appearance:none;-webkit-appearance:none;border:0;background:transparent;color:var(--text);font:var(--fw-semibold) var(--fs-400)/1 var(--font-ui);text-align:left;padding:var(--sp-3) var(--sp-4);border-radius:var(--r-sm);cursor:pointer;-webkit-tap-highlight-color:transparent}",
      ".argus-menu-item:active{background:var(--surface-3)}"
    ].join("");
    document.head.appendChild(s);
  }

  // ---------- bootstrap ----------
  function tryInit() {
    if (window.__argusTerm) { onReady(window.__argusTerm); return true; }
    return false;
  }
  window.addEventListener("argus-term-ready", tryInit);
  if (!tryInit()) {
    var n = 0, iv = setInterval(function () { if (tryInit() || ++n > 100) clearInterval(iv); }, 100);
  }
})();
