"use strict";

const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;

// ── gBrowser: main browser logic object ──────────────────────────────────────
var gBrowser = {

  // State
  _tabs: [],          // [{tab, panel, browser, _progressListener}]
  _currentIndex: -1,
  _prefs: null,
  _strings: null,
  _bookmarks: [],
  _favoritesFile: null,

  // ── Initialisation ─────────────────────────────────────────────────────────
  init: function() {
    // Preferences service
    this._prefs = Cc["@mozilla.org/preferences-service;1"]
                    .getService(Ci.nsIPrefBranch);

    // String bundle
    try {
      var bundleSvc = Cc["@mozilla.org/intl/stringbundle;1"]
                        .getService(Ci.nsIStringBundleService);
      this._strings = bundleSvc.createBundle(
        "chrome://epoch/locale/browser.properties");
    } catch(e) { Cu.reportError(e); }

    // Bookmarks / Favorites
    this._initFavoritesFile();
    this._loadBookmarks();

    // Open first tab with homepage
    var homepage = "about:blank";
    try {
      homepage = this._prefs.getCharPref("browser.startup.homepage");
    } catch(e) {}
    this.addTab(homepage);

    // Title updates on DOMContentLoaded (capture phase catches all frames)
    window.addEventListener("DOMContentLoaded", function(evt) {
      gBrowser._onDOMContentLoaded(evt);
    }, true);

    // Build the Links bar from bookmarks
    this.buildLinksBar();
  },

  // ── Window close ───────────────────────────────────────────────────────────
  onWindowClose: function() {
    this._saveBookmarks();
    return true;
  },

  // ── Tab management ─────────────────────────────────────────────────────────
  addTab: function(url) {
    var tabs      = document.getElementById("browser-tabs");
    var tabpanels = document.getElementById("browser-tabpanels");

    // Create <tab>
    var tab = document.createElement("tab");
    tab.setAttribute("label", this._str("tab.untitled"));
    tabs.appendChild(tab);

    // Create <tabpanel> containing a <browser>
    var panel = document.createElement("tabpanel");
    panel.setAttribute("flex", "1");
    panel.style.padding = "0";

    var b = document.createElement("browser");
    b.setAttribute("type", "content");
    b.setAttribute("flex", "1");
    b.setAttribute("context", "contentContextMenu");
    b.setAttribute("tooltip", "aHTMLTooltip");
    panel.appendChild(b);
    tabpanels.appendChild(panel);

    var idx = this._tabs.length;
    this._tabs.push({ tab: tab, panel: panel, browser: b, _progressListener: null });

    // Attach progress listener before loading
    this._attachProgressListener(b, idx);

    // Select this tab
    this.selectTab(idx);

    // Load URL
    if (url && url !== "about:blank") {
      this.loadURI(url);
    }

    return idx;
  },

  closeCurrentTab: function() {
    if (this._tabs.length <= 1) {
      window.close();
      return;
    }
    var idx   = this._currentIndex;
    var entry = this._tabs[idx];

    // Remove progress listener
    try {
      if (entry._progressListener) {
        entry.browser.removeProgressListener(entry._progressListener);
      }
    } catch(e) {}

    // Remove DOM nodes
    entry.tab.parentNode.removeChild(entry.tab);
    entry.panel.parentNode.removeChild(entry.panel);

    // Remove from array
    this._tabs.splice(idx, 1);

    // Re-index progress listeners that used a captured idx
    // (they reference gBrowser._tabs[idx] via closure — rebuild them)
    for (var i = idx; i < this._tabs.length; i++) {
      try {
        this._tabs[i].browser.removeProgressListener(
          this._tabs[i]._progressListener);
      } catch(e) {}
      this._attachProgressListener(this._tabs[i].browser, i);
    }

    // Select adjacent tab
    var newIdx = Math.min(idx, this._tabs.length - 1);
    this._currentIndex = -1; // force sync
    this.selectTab(newIdx);
  },

  selectTab: function(index) {
    if (index < 0 || index >= this._tabs.length) return;
    var tabbox = document.getElementById("content-tabbox");
    tabbox.selectedIndex = index;
    this._currentIndex = index;
    this._syncUIToCurrentTab();
  },

  onTabSelect: function(event) {
    var tabbox = document.getElementById("content-tabbox");
    this._currentIndex = tabbox.selectedIndex;
    this._syncUIToCurrentTab();
  },

  _syncUIToCurrentTab: function() {
    var idx = this._currentIndex;
    if (idx < 0 || idx >= this._tabs.length) return;
    var entry = this._tabs[idx];
    var b     = entry.browser;

    // URL bar
    var urlbar = document.getElementById("urlbar");
    try {
      var loc = b.currentURI ? b.currentURI.spec : "";
      if (loc === "about:blank") loc = "";
      urlbar.value = loc;
    } catch(e) { urlbar.value = ""; }

    // Window title
    var title = "";
    try { title = b.contentDocument && b.contentDocument.title; } catch(e) {}
    document.title = title ? title + " - Epoch" : "Epoch";

    // Tab label
    entry.tab.setAttribute("label", title || this._str("tab.untitled"));

    // Nav buttons
    this._updateNavButtons();

    // Find bar association
    try {
      var fb = document.getElementById("FindToolbar");
      if (fb) fb.browser = b;
    } catch(e) {}
  },

  // ── Navigation ─────────────────────────────────────────────────────────────
  go: function() {
    var urlbar = document.getElementById("urlbar");
    var input  = urlbar.value.trim();
    if (!input) return;

    var uri;
    if (this._looksLikeURL(input)) {
      uri = input;
      if (!/^[a-zA-Z][a-zA-Z0-9+\-.]*:/.test(uri)) {
        uri = "https://" + uri;
      }
    } else {
      uri = "https://www.google.com/search?q=" + encodeURIComponent(input);
    }
    this.loadURI(uri);
  },

  loadURI: function(uri) {
    var b = this._currentBrowser();
    if (!b) return;
    var flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
    try {
      b.webNavigation.loadURI(uri, flags, null, null, null);
    } catch(e) {
      // Retry with https:// prefix
      try {
        b.webNavigation.loadURI("https://" + uri, flags, null, null, null);
      } catch(e2) {
        Cu.reportError("loadURI failed: " + e2);
      }
    }
  },

  _looksLikeURL: function(s) {
    // Has a scheme
    if (/^[a-zA-Z][a-zA-Z0-9+\-.]*:/.test(s)) return true;
    // localhost or numeric IP
    if (/^localhost(:\d+)?/.test(s)) return true;
    if (/^\d{1,3}(\.\d{1,3}){3}(:\d+)?/.test(s)) return true;
    // domain-like: word.tld (at least two dot-separated parts, no spaces)
    if (/\s/.test(s)) return false;
    if (/^[^.]+\.[^.]{2,}/.test(s)) return true;
    return false;
  },

  back: function() {
    var b = this._currentBrowser();
    if (b && b.webNavigation.canGoBack) {
      b.webNavigation.goBack();
    }
  },

  forward: function() {
    var b = this._currentBrowser();
    if (b && b.webNavigation.canGoForward) {
      b.webNavigation.goForward();
    }
  },

  reload: function() {
    var b = this._currentBrowser();
    if (b) {
      b.webNavigation.reload(Ci.nsIWebNavigation.LOAD_FLAGS_NONE);
    }
  },

  stop: function() {
    var b = this._currentBrowser();
    if (b) {
      b.webNavigation.stop(Ci.nsIWebNavigation.STOP_ALL);
    }
  },

  goHome: function() {
    var hp = "https://www.google.com/";
    try { hp = this._prefs.getCharPref("browser.startup.homepage"); } catch(e) {}
    this.loadURI(hp);
  },

  onURLBarKeyPress: function(event) {
    if (event.keyCode === KeyEvent.DOM_VK_RETURN ||
        event.keyCode === KeyEvent.DOM_VK_ENTER) {
      this.go();
    }
  },

  focusURLBar: function() {
    var urlbar = document.getElementById("urlbar");
    if (urlbar) {
      urlbar.focus();
      urlbar.select();
    }
  },

  // ── Progress listener ──────────────────────────────────────────────────────
  _attachProgressListener: function(browser, idx) {
    var listener = {
      _idx: idx,

      onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) {
        if (aStateFlags & Ci.nsIWebProgressListener.STATE_START) {
          // Show loading indicators only for current tab
          if (gBrowser._currentIndex === this._idx) {
            document.getElementById("throbber").removeAttribute("hidden");
            document.getElementById("stop-button").removeAttribute("disabled");
            document.getElementById("progress-bar").removeAttribute("hidden");
            document.getElementById("status-text").setAttribute(
              "label", gBrowser._str("status.loading"));
          }
          gBrowser._tabs[this._idx] &&
            gBrowser._tabs[this._idx].tab.setAttribute("busy", "true");
        }
        if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
          if (gBrowser._currentIndex === this._idx) {
            document.getElementById("throbber").setAttribute("hidden", "true");
            document.getElementById("stop-button").setAttribute("disabled", "true");
            document.getElementById("progress-bar").setAttribute("hidden", "true");
            document.getElementById("status-text").setAttribute(
              "label", gBrowser._str("status.done"));
            gBrowser._syncUIToCurrentTab();
          }
          gBrowser._tabs[this._idx] &&
            gBrowser._tabs[this._idx].tab.removeAttribute("busy");
        }
      },

      onProgressChange: function(aWebProgress, aRequest,
                                  aCurSelf, aMaxSelf, aCurTotal, aMaxTotal) {
        if (gBrowser._currentIndex !== this._idx) return;
        var pm = document.getElementById("progress-bar");
        if (aMaxTotal > 0) {
          pm.value = Math.round((aCurTotal / aMaxTotal) * 100);
        } else {
          pm.mode = "undetermined";
        }
      },

      onLocationChange: function(aWebProgress, aRequest, aLocation) {
        if (gBrowser._currentIndex !== this._idx) return;
        var spec = aLocation ? aLocation.spec : "";
        if (spec === "about:blank") spec = "";
        document.getElementById("urlbar").value = spec;
        gBrowser._updateNavButtons();
        gBrowser._updateSecurityUI(aLocation);
      },

      onStatusChange: function(aWebProgress, aRequest, aStatus, aMessage) {
        if (gBrowser._currentIndex !== this._idx) return;
        document.getElementById("status-text").setAttribute("label", aMessage);
      },

      onSecurityChange: function(aWebProgress, aRequest, aState) {
        if (gBrowser._currentIndex !== this._idx) return;
        var icon = document.getElementById("security-icon");
        var STATE_IS_SECURE = Ci.nsIWebProgressListener.STATE_IS_SECURE;
        var STATE_IS_BROKEN  = Ci.nsIWebProgressListener.STATE_IS_BROKEN;
        if (aState & STATE_IS_SECURE) {
          icon.setAttribute("level", "high");
        } else if (aState & STATE_IS_BROKEN) {
          icon.setAttribute("level", "broken");
        } else {
          icon.setAttribute("level", "none");
        }
      },

      QueryInterface: function(aIID) {
        if (aIID.equals(Ci.nsIWebProgressListener) ||
            aIID.equals(Ci.nsISupportsWeakReference) ||
            aIID.equals(Ci.nsISupports)) {
          return this;
        }
        throw Components.results.NS_NOINTERFACE;
      }
    };

    browser.addProgressListener(listener, Ci.nsIWebProgress.NOTIFY_ALL);
    this._tabs[idx]._progressListener = listener;
  },

  // ── Nav button state ───────────────────────────────────────────────────────
  _updateNavButtons: function() {
    var b = this._currentBrowser();
    var backBtn    = document.getElementById("back-button");
    var forwardBtn = document.getElementById("forward-button");
    if (!b) return;
    if (b.webNavigation.canGoBack) {
      backBtn.removeAttribute("disabled");
    } else {
      backBtn.setAttribute("disabled", "true");
    }
    if (b.webNavigation.canGoForward) {
      forwardBtn.removeAttribute("disabled");
    } else {
      forwardBtn.setAttribute("disabled", "true");
    }
  },

  _updateSecurityUI: function(location) {
    var icon = document.getElementById("security-icon");
    if (!location) {
      icon.setAttribute("level", "none");
      return;
    }
    var scheme = location.scheme || "";
    if (scheme === "https") {
      icon.setAttribute("level", "high");
    } else {
      icon.setAttribute("level", "none");
    }
  },

  // ── DOMContentLoaded handler ───────────────────────────────────────────────
  _onDOMContentLoaded: function(evt) {
    var doc = evt.originalTarget;
    if (!doc || doc.nodeType !== Node.DOCUMENT_NODE) return;

    // Find which tab owns this document
    for (var i = 0; i < this._tabs.length; i++) {
      try {
        if (this._tabs[i].browser.contentDocument === doc) {
          var title = doc.title || this._str("tab.untitled");
          this._tabs[i].tab.setAttribute("label", title);
          if (i === this._currentIndex) {
            document.title = title + " - Epoch";
          }
          break;
        }
      } catch(e) {}
    }
  },

  // ── Zoom ───────────────────────────────────────────────────────────────────
  zoomIn: function() {
    var b = this._currentBrowser();
    if (b) {
      b.markupDocumentViewer.fullZoom *= 1.1;
    }
  },

  zoomOut: function() {
    var b = this._currentBrowser();
    if (b) {
      b.markupDocumentViewer.fullZoom /= 1.1;
    }
  },

  zoomReset: function() {
    var b = this._currentBrowser();
    if (b) {
      b.markupDocumentViewer.fullZoom = 1.0;
    }
  },

  // ── Find bar ───────────────────────────────────────────────────────────────
  toggleFindBar: function() {
    var fb = document.getElementById("FindToolbar");
    if (!fb) return;
    if (fb.hidden) {
      fb.removeAttribute("hidden");
      fb.browser = this._currentBrowser();
      fb.startFind(Ci.nsITypeAheadFind.FIND_NORMAL);
    } else {
      fb.setAttribute("hidden", "true");
      fb.close();
    }
  },

  // ── Toolbar / statusbar toggles ────────────────────────────────────────────
  toggleToolbar: function() {
    var bar = document.getElementById("nav-bar");
    if (bar) bar.hidden = !bar.hidden;
  },

  toggleStatusBar: function() {
    var sb = document.getElementById("status-bar");
    if (sb) sb.hidden = !sb.hidden;
  },

  // ── Favorites (Bookmarks) ─────────────────────────────────────────────────
  _initFavoritesFile: function() {
    try {
      var dirSvc = Cc["@mozilla.org/file/directory_service;1"]
                     .getService(Ci.nsIProperties);
      this._favoritesFile = dirSvc.get("ProfD", Ci.nsIFile);
      this._favoritesFile.append("epoch-favorites.json");
    } catch(e) { Cu.reportError(e); }
  },

  _loadBookmarks: function() {
    this._bookmarks = [];
    if (!this._favoritesFile || !this._favoritesFile.exists()) return;
    try {
      var fis = Cc["@mozilla.org/network/file-input-stream;1"]
                  .createInstance(Ci.nsIFileInputStream);
      fis.init(this._favoritesFile, -1, 0, 0);
      var sis = Cc["@mozilla.org/scriptableinputstream;1"]
                  .createInstance(Ci.nsIScriptableInputStream);
      sis.init(fis);
      var json = sis.read(sis.available());
      sis.close();
      fis.close();
      this._bookmarks = JSON.parse(json) || [];
    } catch(e) { Cu.reportError(e); }
  },

  _saveBookmarks: function() {
    if (!this._favoritesFile) return;
    try {
      var json = JSON.stringify(this._bookmarks, null, 2);
      var fos = Cc["@mozilla.org/network/file-output-stream;1"]
                  .createInstance(Ci.nsIFileOutputStream);
      fos.init(this._favoritesFile, 0x02 | 0x08 | 0x20, 0o644, 0);
      fos.write(json, json.length);
      fos.close();
    } catch(e) { Cu.reportError(e); }
  },

  addBookmark: function() {
    var b = this._currentBrowser();
    if (!b) return;
    var url   = "";
    var title = "";
    try {
      url   = b.currentURI.spec;
      title = b.contentDocument.title || url;
    } catch(e) { return; }

    if (!url || url === "about:blank") return;

    // Check for duplicates
    for (var i = 0; i < this._bookmarks.length; i++) {
      if (this._bookmarks[i].url === url) {
        alert("This page is already in your Favorites.");
        return;
      }
    }

    var name = prompt("Add to Favorites\n\nName:", title);
    if (name === null) return; // cancelled
    if (!name) name = url;

    this._bookmarks.push({ title: name, url: url });
    this._saveBookmarks();
    this.buildLinksBar();
    alert('"' + name + '" has been added to your Favorites.');
  },

  manageBookmarks: function() {
    // Simple text-based manager — list URLs and allow deletion by number
    if (!this._bookmarks.length) {
      alert("Your Favorites list is empty.");
      return;
    }
    var list = this._bookmarks.map(function(b, i) {
      return (i + 1) + ". " + b.title + "\n   " + b.url;
    }).join("\n\n");
    var input = prompt(
      "Organize Favorites\n\nEnter a number to delete that favorite, or Cancel to close:\n\n" + list);
    if (!input) return;
    var num = parseInt(input, 10) - 1;
    if (num >= 0 && num < this._bookmarks.length) {
      var removed = this._bookmarks.splice(num, 1);
      this._saveBookmarks();
      this.buildLinksBar();
      alert('"' + removed[0].title + '" removed from Favorites.');
    }
  },

  buildFavoritesMenu: function(event) {
    var popup = document.getElementById("menu-favorites-popup");
    var sep   = document.getElementById("favorites-separator");

    // Remove any previously built items (after the separator)
    var child = sep.nextSibling;
    while (child) {
      var next = child.nextSibling;
      popup.removeChild(child);
      child = next;
    }

    // Add one menuitem per bookmark
    for (var i = 0; i < this._bookmarks.length; i++) {
      var item = document.createElement("menuitem");
      item.setAttribute("label", this._bookmarks[i].title);
      item.setAttribute("tooltiptext", this._bookmarks[i].url);
      (function(url) {
        item.addEventListener("command", function() {
          gBrowser.loadURI(url);
        }, false);
      })(this._bookmarks[i].url);
      popup.appendChild(item);
    }
  },

  buildLinksBar: function() {
    var box = document.getElementById("links-buttons");
    if (!box) return;

    // Clear existing buttons
    while (box.firstChild) box.removeChild(box.firstChild);

    // Add up to 8 bookmark buttons
    var max = Math.min(this._bookmarks.length, 8);
    for (var i = 0; i < max; i++) {
      var btn = document.createElement("toolbarbutton");
      btn.setAttribute("label", this._bookmarks[i].title);
      btn.setAttribute("tooltiptext", this._bookmarks[i].url);
      btn.setAttribute("class", "links-bar-btn");
      (function(url) {
        btn.addEventListener("command", function() {
          gBrowser.loadURI(url);
        }, false);
      })(this._bookmarks[i].url);
      box.appendChild(btn);
    }
  },

  // ── Context menu ───────────────────────────────────────────────────────────
  buildContextMenu: function(event) {
    var copyLink     = document.getElementById("ctx-copyLink");
    var openNewTab   = document.getElementById("ctx-openLinkNewTab");
    var node         = document.popupNode;

    // Walk up DOM to find anchor
    var anchor = null;
    var cur = node;
    while (cur && cur.nodeType === Node.ELEMENT_NODE) {
      if (cur.tagName && cur.tagName.toLowerCase() === "a") {
        anchor = cur;
        break;
      }
      cur = cur.parentNode;
    }

    var hasLink = anchor && anchor.href;
    copyLink.hidden   = !hasLink;
    openNewTab.hidden = !hasLink;
  },

  copyLink: function(event) {
    var node = document.popupNode;
    var cur  = node;
    while (cur && cur.nodeType === Node.ELEMENT_NODE) {
      if (cur.tagName && cur.tagName.toLowerCase() === "a") break;
      cur = cur.parentNode;
    }
    if (cur && cur.href) {
      var clip = Cc["@mozilla.org/widget/clipboardhelper;1"]
                   .getService(Ci.nsIClipboardHelper);
      clip.copyString(cur.href);
    }
  },

  openLinkInNewTab: function(event) {
    var node = document.popupNode;
    var cur  = node;
    while (cur && cur.nodeType === Node.ELEMENT_NODE) {
      if (cur.tagName && cur.tagName.toLowerCase() === "a") break;
      cur = cur.parentNode;
    }
    if (cur && cur.href) {
      this.addTab(cur.href);
    }
  },

  // ── File operations ────────────────────────────────────────────────────────
  openFile: function() {
    var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
    fp.init(window, "Open File", Ci.nsIFilePicker.modeOpen);
    fp.appendFilters(Ci.nsIFilePicker.filterHTML |
                     Ci.nsIFilePicker.filterText |
                     Ci.nsIFilePicker.filterAll);
    var result = fp.show();
    if (result === Ci.nsIFilePicker.returnOK) {
      this.loadURI(fp.fileURL.spec);
    }
  },

  savePageAs: function() {
    var b = this._currentBrowser();
    if (!b) return;
    var doc = null;
    try { doc = b.contentDocument; } catch(e) { return; }

    var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
    fp.init(window, "Save Page As", Ci.nsIFilePicker.modeSave);
    fp.defaultString = "index.html";
    fp.appendFilter("Web Page, complete (*.html)", "*.html; *.htm");
    fp.appendFilter("Text files (*.txt)", "*.txt");
    fp.appendFilters(Ci.nsIFilePicker.filterAll);
    var result = fp.show();
    if (result !== Ci.nsIFilePicker.returnOK &&
        result !== Ci.nsIFilePicker.returnReplace) return;

    try {
      var persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
                      .createInstance(Ci.nsIWebBrowserPersist);
      persist.persistFlags =
        Ci.nsIWebBrowserPersist.PERSIST_FLAGS_REPLACE_EXISTING_FILES;
      persist.saveDocument(doc, fp.file, null, null, 0, 0);
    } catch(e) { Cu.reportError(e); alert("Save failed: " + e); }
  },

  printPage: function() {
    var b = this._currentBrowser();
    if (!b) return;
    try {
      var pp = Cc["@mozilla.org/printing/printengine;1"]
                 .getService(Ci.nsIPrintEngine);
      pp.print(b.contentWindow, null);
    } catch(e) {
      // Fallback: use window.print() on the content window
      try { b.contentWindow.print(); } catch(e2) { Cu.reportError(e2); }
    }
  },

  openNewWindow: function() {
    window.open("chrome://epoch/content/browser.xul", "",
                "chrome,all,dialog=no,resizable");
  },

  // ── About dialog ───────────────────────────────────────────────────────────
  openAboutDialog: function() {
    window.openDialog("chrome://epoch/content/aboutDialog.xul",
                      "about", "chrome,centerscreen,modal,resizable=no");
  },

  // ── Options (placeholder) ──────────────────────────────────────────────────
  openPreferences: function() {
    alert("Options not yet implemented in this build.");
  },

  // ── View Source ────────────────────────────────────────────────────────────
  viewSource: function() {
    var b = this._currentBrowser();
    if (!b) return;
    var uri = "";
    try { uri = b.currentURI.spec; } catch(e) { return; }
    window.open("view-source:" + uri, "",
                "chrome,all,dialog=no,resizable");
  },

  // ── Page Info ──────────────────────────────────────────────────────────────
  viewPageInfo: function() {
    var b = this._currentBrowser();
    if (!b) return;
    try {
      window.openDialog("chrome://browser/content/pageinfo/pageInfo.xul",
                        "page-info", "chrome,centerscreen,resizable");
    } catch(e) {
      // Fallback: show basic info
      var uri   = "";
      var title = "";
      try { uri   = b.currentURI.spec; }         catch(e2) {}
      try { title = b.contentDocument.title; }   catch(e2) {}
      alert("Page Info\n\nTitle: " + title + "\nURL: " + uri);
    }
  },

  // ── Clear browsing data ────────────────────────────────────────────────────
  clearBrowsingData: function() {
    var confirm = window.confirm(
      "Delete Browsing History?\n\nThis will clear your cached pages and browsing history.");
    if (!confirm) return;

    // Clear cache
    try {
      var cacheSvc = Cc["@mozilla.org/network/cache-service;1"]
                       .getService(Ci.nsICacheService);
      cacheSvc.evictEntries(Ci.nsICache.STORE_ANYWHERE);
    } catch(e) { Cu.reportError(e); }

    // Clear history
    try {
      var histSvc = Cc["@mozilla.org/browser/global-history;2"]
                      .getService(Ci.nsIBrowserHistory);
      histSvc.removeAllPages();
    } catch(e) { Cu.reportError(e); }

    alert("Browsing history cleared.");
  },

  // ── Helper: current browser element ───────────────────────────────────────
  _currentBrowser: function() {
    if (this._currentIndex < 0 || this._currentIndex >= this._tabs.length) {
      return null;
    }
    return this._tabs[this._currentIndex].browser;
  },

  // ── Helper: string bundle lookup ──────────────────────────────────────────
  _str: function(key) {
    try {
      return this._strings.GetStringFromName(key);
    } catch(e) {
      // Return key as fallback
      return key;
    }
  }
};
