var username, usernameForm;
username = window.localStorage.getItem("username");
saveUsername();

function saveUsername() {
  if (usernameForm && usernameForm.value) {
    username = usernameForm.value;
    window.localStorage.setItem("username", username);
    window.localStorage.setItem("usernamePixel", username);
    console.log("Username saved: " + username);
  } else {
    console.log("no username detected");
  }
}

document.addEventListener("DOMContentLoaded", function (event) {
  usernameListener();


  waitForElementRetry("#register_form", {maxRetries: 3, timeout: 99999}).then(() => {
    usernameListener();
  });

  waitForElementRetry("[name='username']", {maxRetries: 3, timeout: 99999}).then(() => {
    usernameListener();
  })
});

function usernameListener() {
  var typingTimer;
  usernameForm = document.querySelector(
    'span.username, .username-container > span, #username_field, [name="UserName"], [name="username"], #UserName, #username, #Username',
  );
  if (usernameForm) {
    usernameForm.addEventListener("keyup", function () {
      clearTimeout(typingTimer);
      if (usernameForm.value) {
        typingTimer = setTimeout(saveUsername, 1000);
      }
    });
  }
}

if (window.location.search) {
  console.log("Query params saved: " + window.location.search);
  window.localStorage.setItem("queryParams", window.location.search);
} else {
  if (!document.referrer.includes(window.location.hostname)) {
    window.localStorage.removeItem("queryParams");
  }
}

if (!document.referrer.includes(window.location.hostname)) {
  console.log("Document referrer saved: " + document.referrer);
  window.localStorage.setItem("documentReferrer", document.referrer);
}

const searchParams = ["opera_click_id", "click_id", "clickid"];

try {
  const paramsExists = getStoredQueryParams(searchParams);
  // Ensure we actually have a valid object before proceeding
  if (
    paramsExists &&
    typeof paramsExists === "object" &&
    Object.keys(paramsExists).length > 0
  ) {
    appendQueryParams(window.location.href, paramsExists);
  }
} catch (e) {
  console.warn("Unable to restore query params", e);
}
function getStoredQueryParams(params) {
  if (!params) return null;
  // Safety check for SSR or environments without window
  if (typeof window === "undefined") return null;
  const queryParams = window.localStorage.getItem("queryParams") ?? "";
  if (!queryParams) return null;
  const storedQueryParams = new URLSearchParams(queryParams);
  const results = {};
  // Normalize input to array to simplify logic
  const keysToSearch = Array.isArray(params) ? params : [params];
  for (const param of keysToSearch) {
    const storedValue = storedQueryParams.get(param);
    // Only return if found
    if (storedValue) {
      results[param] = storedValue;
    }
  }
  return results;
}
function appendQueryParams(url, params) {
  const urlObj = new URL(url);
  let hasChanges = false;
  for (const param in params) {
    // OPTIONAL: Only set if NOT currently in URL (preserve new marketing clicks)
    if (!urlObj.searchParams.has(param)) {
      urlObj.searchParams.set(param, params[param]);
      hasChanges = true;
    }
    // If you prefer to ALWAYS overwrite, remove the if check above
  }
  if (hasChanges) {
    // Use replaceState to avoid trapping user in back-button loop
    window.history.replaceState({}, "", urlObj);
  }
}

function waitForElement(selector, { timeout = 10000, interval = 300 } = {}) {
  return new Promise((resolve, reject) => {
    const existing = document.querySelector(selector);
    if (existing) return resolve(existing);

    if (window.MutationObserver) {
      const observer = new MutationObserver(() => {
        const el = document.querySelector(selector);
        if (el) {
          observer.disconnect();
          resolve(el);
        }
      });

      observer.observe(document.documentElement, {
        childList: true,
        subtree: true,
      });

      setTimeout(() => {
        observer.disconnect();
        reject(new Error("Timeout waiting for element"));
      }, timeout);
    } else {
      const start = Date.now();
      const timer = setInterval(() => {
        const el = document.querySelector(selector);
        if (el) {
          clearInterval(timer);
          resolve(el);
        } else if (Date.now() - start > timeout) {
          clearInterval(timer);
          reject(new Error("Timeout waiting for element"));
        }
      }, interval);
    }
  });
}

function waitForElementV2(selector, { timeout = 10000, root = document } = {}) {
  return new Promise((resolve, reject) => {
    const existing = root.querySelector(selector);
    if (existing) return resolve(existing);

    if (!window.MutationObserver) {
      const start = Date.now();
      const timer = setInterval(() => {
        const el = root.querySelector(selector);
        if (el) { clearInterval(timer); resolve(el); }
        else if (Date.now() - start > timeout) { clearInterval(timer); reject(new Error("Timeout waiting for element")); }
      }, 300);
      return;
    }

    let rafScheduled = false;
    let settled = false;

    const observer = new MutationObserver(() => {
      if (settled || rafScheduled) return;
      rafScheduled = true;

      requestAnimationFrame(() => {
        rafScheduled = false;
        if (settled) return;

        const el = root.querySelector(selector);
        if (el) {
          settled = true;
          observer.disconnect();
          clearTimeout(timeoutId);
          resolve(el);
        }
      });
    });

    observer.observe(root === document ? document.documentElement : root, {
      childList: true,
      subtree: true,
    });

    const timeoutId = setTimeout(() => {
      if (settled) return;
      settled = true;
      observer.disconnect();
      reject(new Error("Timeout waiting for element"));
    }, timeout);
  });
}

function waitForElementRetry(
  selector,
  {
    root = document,
    timeout = 5000,        // per attempt
    maxRetries = 3,        // number of retries after first attempt
    backoffBase = 400,     // ms
    backoffFactor = 1.7,   // exponential factor
    jitter = 0.25,         // 25% random jitter
    interval = 250,        // polling interval fallback
    observeAttributes = false, // if you need attribute toggles
  } = {}
) {
  let attempt = 0;

  const calcDelay = (n) => {
    const exp = backoffBase * Math.pow(backoffFactor, n);
    const j = exp * jitter * (Math.random() * 2 - 1); // +/- jitter
    return Math.max(0, Math.floor(exp + j));
  };

  const tryOnce = () =>
    waitForElementOnce(selector, {
      root,
      timeout,
      interval,
      observeAttributes,
    });

  return new Promise((resolve, reject) => {
    const run = () => {
      tryOnce()
        .then(resolve)
        .catch((err) => {
          if (attempt >= maxRetries) {
            reject(err);
            return;
          }
          const delay = calcDelay(attempt);
          attempt += 1;
          setTimeout(run, delay);
        });
    };

    run();
  });
}

function waitForElementOnce(
  selector,
  { root = document, timeout = 5000, interval = 250, observeAttributes = false } = {}
) {
  return new Promise((resolve, reject) => {
    const scope = root instanceof Document ? root : root;

    const find = () => scope.querySelector(selector);

    const existing = find();
    if (existing) return resolve(existing);

    let settled = false;
    let timeoutId = null;
    let observer = null;
    let timer = null;

    const cleanup = () => {
      if (observer) observer.disconnect();
      if (timer) clearInterval(timer);
      if (timeoutId) clearTimeout(timeoutId);
      observer = null;
      timer = null;
      timeoutId = null;
    };

    const doneResolve = (el) => {
      if (settled) return;
      settled = true;
      cleanup();
      resolve(el);
    };

    const doneReject = (err) => {
      if (settled) return;
      settled = true;
      cleanup();
      reject(err);
    };

    timeoutId = setTimeout(() => {
      doneReject(new Error(`Timeout waiting for element: ${selector}`));
    }, timeout);

    if (window.MutationObserver) {
      // Observe a sensible root for DOM changes
      const observeRoot =
        scope instanceof Document
          ? scope.documentElement
          : scope;

      let rafScheduled = false;

      observer = new MutationObserver(() => {
        if (settled || rafScheduled) return;
        rafScheduled = true;

        requestAnimationFrame(() => {
          rafScheduled = false;
          if (settled) return;

          const el = find();
          if (el) doneResolve(el);
        });
      });

      observer.observe(observeRoot, {
        childList: true,
        subtree: true,
        attributes: observeAttributes,
      });
    } else {
      timer = setInterval(() => {
        const el = find();
        if (el) doneResolve(el);
      }, interval);
    }
  });
}