(function () {
  "use strict";

  var cfg = null;
  var filledKeys = {};
  var startedAt = Date.now();
  var MAX_MS = 120000;

  function loadConfig(cb) {
    try {
      var rt = typeof browser !== "undefined" ? browser : chrome;
      var url = rt.runtime.getURL("autofill_config.json");
      fetch(url, { cache: "no-store" })
        .then(function (r) { return r.json(); })
        .then(function (j) { cb(j || null); })
        .catch(function () { cb(null); });
    } catch (e) {
      cb(null);
    }
  }

  function hostMatches(host, patterns) {
    if (!patterns || !patterns.length) return true;
    host = (host || "").toLowerCase();
    for (var i = 0; i < patterns.length; i++) {
      var p = String(patterns[i] || "").toLowerCase();
      if (!p) continue;
      if (p.indexOf("*") >= 0) {
        var re = new RegExp("^" + p.replace(/\./g, "\\.").replace(/\*/g, ".*") + "$");
        if (re.test(host)) return true;
      } else if (host === p || host.endsWith("." + p)) {
        return true;
      }
    }
    return false;
  }

  function setValue(el, value) {
    if (!el || value == null || value === "") return false;
    try {
      el.focus();
      el.value = value;
      el.dispatchEvent(new Event("input", { bubbles: true }));
      el.dispatchEvent(new Event("change", { bubbles: true }));
      return true;
    } catch (e) {
      return false;
    }
  }

  function trySelectors(selectors, value) {
    if (!selectors || !value) return false;
    for (var i = 0; i < selectors.length; i++) {
      var nodes = document.querySelectorAll(selectors[i]);
      for (var j = 0; j < nodes.length; j++) {
        var el = nodes[j];
        if (!el || el.disabled || el.readOnly) continue;
        if (el.type === "hidden") continue;
        if (setValue(el, value)) return true;
      }
    }
    return false;
  }

  function runFill() {
    if (!cfg || !cfg.fields) return;
    if (Date.now() - startedAt > MAX_MS) return;
    var host = location.hostname || "";
    if (cfg.hosts && cfg.hosts.length && !hostMatches(host, cfg.hosts)) return;

    var fields = cfg.fields;
    var keys = Object.keys(fields);
    for (var i = 0; i < keys.length; i++) {
      var key = keys[i];
      var val = fields[key];
      if (!val) continue;
      if (filledKeys[key]) continue;
      if (trySelectors(fields[key + "_selectors"] || defaultSelectors(key), val)) {
        filledKeys[key] = true;
      }
    }
  }

  function defaultSelectors(key) {
    var map = {
      email: [
        'input[type="email"]',
        'input[name="email"]',
        'input[name="Email"]',
        'input[id="email"]',
        'input[autocomplete="email"]',
        'input[autocomplete="username"]',
        'input[name="identifier"]'
      ],
      password: [
        'input[type="password"]:not([name*="Confirm"]):not([name*="confirm"]):not([name*="Again"]):not([name*="again"])',
        'input[name="password"]',
        'input[name="Passwd"]',
        'input[id="password"]',
        'input[autocomplete="new-password"]'
      ],
      password_confirm: [
        'input[name="PasswdAgain"]',
        'input[name="password_confirm"]',
        'input[name="confirmPassword"]',
        'input[name="passwordConfirmation"]',
        'input[autocomplete="new-password"]:nth-of-type(2)'
      ],
      first_name: [
        'input[name="firstName"]',
        'input[name="firstname"]',
        'input[name="first_name"]',
        'input[autocomplete="given-name"]'
      ],
      last_name: [
        'input[name="lastName"]',
        'input[name="lastname"]',
        'input[name="last_name"]',
        'input[autocomplete="family-name"]'
      ],
      username: [
        'input[name="username"]',
        'input[name="Username"]',
        'input[id="username"]',
        'input[autocomplete="username"]'
      ]
    };
    return map[key] || [];
  }

  function boot() {
    loadConfig(function (j) {
      cfg = j;
      if (!cfg) return;
      runFill();
      var obs = new MutationObserver(function () { runFill(); });
      obs.observe(document.documentElement || document.body, {
        childList: true,
        subtree: true
      });
      var timer = setInterval(function () {
        runFill();
        if (Date.now() - startedAt > MAX_MS) clearInterval(timer);
      }, 900);
    });
  }

  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", boot);
  } else {
    boot();
  }
})();
