// ==UserScript==
// @name        Flag Randomizer
// @namespace   http://ponepaste.org/5555
// @match       https://boards.4channel.org/mlp/thread/*
// @match       https://boards.4chan.org/mlp/thread/*
// @grant       none
// @version     1.18
// @author      Fillyanon, ScriptFilly
// @description Adds a flag randomizer to the Board.
// ==/UserScript==

'use strict'

let changeFlagOnKeyStroke = true;

const flags = Object.freeze({
  MISC: ["4CC", "AN"],

  G4: [
    "AJ",
    "ANF",
    "APB",
    "AU",
    "BB",
    "BM",
    "BP",
    "BS",
    "CB",
    "CG",
    "CHE",
    "CL",
    "CO",
    "DAY",
    "DD",
    "DER",
    "DIS",
    "DT",
    "FAU",
    "FL",
    "FLE",
    "GI",
    "LI",
    "LT",
    "LY",
    "MA",
    "MAU",
    "MIN",
    "NI",
    "NUR",
    "OCT",
    "PAR",
    "PC",
    "PCE",
    "PI",
    "PLU",
    "PM",
    "QC",
    "RAR",
    "RD",
    "RLU",
    "S1L",
    "SCO",
    "SHI",
    "SIL",
    "SP",
    "SPI",
    "STA",
    "STL",
    "SUN",
    "SUS",
    "SWB",
    "TS",
    "TWI",
    "TX",
    "VS",
    "ZE",
  ],

  G5: ["HT", "IZ", "PP", "SPT", "ZS", "SS"],

  EQG: [
    "ADA",
    "AB",
    "SON",
    "EQA",
    "EQF",
    "EQP",
    "EQR",
    "EQT",
    "EQI",
    "EQS",
    "ERA",
  ],

  TFH: ["TFA", "TFO", "TFP", "TFS", "TFT", "TFV", "TP"],
});

// Collects all flags into a single, flat array.
const allFlags = Object.values(flags).flat();

// Returns a random element from an array.
const getRand = (coll) => {
  return coll[Math.floor(Math.random() * coll.length)];
};

const makeOpt = (option) => {
  const opt = document.createElement("option");
  opt.value = opt.innerText = option;
  selector.appendChild(opt);
}

const getPost = (use4chanX) => {
  let post = (use4chanX !== "") ? use4chanX : document.forms.post;
  return post;
}

let handler = false;

const changeFlag = () => {
  let flagSelector = post.querySelector(".flagSelector");
  if (selector.value == "OFF") return;
  flagSelector.value = (selector.value != "ALL") ? getRand(flags[selector.value]) : getRand(allFlags);
}

const selector = document.createElement("select");
const botLine = document.querySelector('.navLinksBot');

selector.style = "margin-left: 1rem;";
selector.addEventListener("change", () => {
  window.localStorage.setItem("flagGroup", selector.value);
});

Object.keys(flags).forEach((key) => {makeOpt(key);});
makeOpt("ALL");
makeOpt("OFF");
selector.value = window.localStorage.getItem("flagGroup") ?? "G4";

botLine.appendChild(selector);

function debounce(func, wait, immediate) {
  var timeout;
  return function() {
    var context = this, args = arguments;
    var later = function() {
      timeout = null;
      if (!immediate) func.apply(context, args);
    };
    var callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) func.apply(context, args);
  };
}
var myEfficientFn = debounce(function() { changeFlag(); }, 250, false);

let handled = true;
if (changeFlagOnKeyStroke == true) {
  const config = {attributes: true, childList: true, subtree: true};
  const callback = function (mutations, _) {
    for (const mutation of mutations) {
      if (mutation.type === 'childList') { // When new child is added
        let use4chanX = document.getElementById("qr") ?? document.getElementById("quickReply") ?? "";
        post = getPost(use4chanX);

        // Do nothing if post is not loaded
        if (post == null || post == undefined) {return;}

        // Else update the flag
        let reply = (use4chanX !== "") ? use4chanX.childNodes[1][5] : post[8];
        reply.addEventListener('input', myEfficientFn);
      }
    }
  };
  const observer = new MutationObserver(callback);
  observer.observe(document, config);
} else {
  setInterval(() => {
    let use4chanX = document.getElementById("qr") ?? "";
    post = getPost(use4chanX);
    if (post == null || post == undefined) { return; }
    changeFlag();
  }, 500);
}