const AUTHORIZED_ALLIANCES = {
    "s58": ["NAZGUL"]
};

function num(s) {
	return parseInt(s.replace(".", ""));
}

function str(n) {
	if (n === 0) {
		return "0";
	}
	let s = "";
	while (n > 0) {
		if (s !== "") {
			s = "." + s;
		}
		let r = n % 1000;
		s = r.toString().padStart(3, "0") + s;
		n = ~~(n/1000);
	}
	return s.replace(/^0+/, "");
}

function createCustomElement(tag, attrs, text, style) {
    let elt = document.createElement(tag);
    if (attrs) {
        for (let [key, value] of Object.entries(attrs)) {
            if (value !== null) {
                elt.setAttribute(key, value.toString());
            }
        }
    }
    if (text) {
        elt.textContent = text.toString();
    }
    if (style) {
        for (let [key, value] of Object.entries(style)) {
            elt.style[key] = value.toString();
        }
    }
    return elt;
}

function createCustomInput(type, name, value, attrs, style) {
    let mergedAttrs = {};
    if (attrs) {
        mergedAttrs = attrs;
    }
    mergedAttrs["type"] = type;
    if (name) {
        mergedAttrs["name"] = name;
    }
    if (value) {
        mergedAttrs["value"] = value;
    }
    return createCustomElement("input", mergedAttrs, null, style);
}

function createKeyValueRow(key, value) {
    let row = createCustomElement("tr");
    let keyCell = createCustomElement("td", null, key);
    let valueCell = createCustomElement("td", null, value);
    row.appendChild(keyCell);
    row.appendChild(valueCell);
    return row;
}

function searchPoint(text) {
    let index = text.search(/\d{3}\|\d{3}/);
    let point = text.slice(index, index + 7).split("|");
    return {x: point[0], y: point[1]}
}

function shortcutElementReplace(elt, img, text) {
    // If more than one hyperlink element found,
    // then keep the last one but with href of the first one.
    let aElements = elt.getElementsByTagName("a");
    let imgElements = elt.getElementsByTagName("img");
    if (aElements.length > 1 || imgElements.length > 0) {
        aElements[aElements.length - 1].classList.add("has_notif");
        aElements[aElements.length - 1].setAttribute("href", aElements[0].getAttribute("href"));
        for (let i = imgElements.length - 1; i >= 0; i--) {
            imgElements[i].remove();
        }
        for (let i = aElements.length - 2; i >= 0; i--) {
            aElements[i].remove();
        }
    }

    let spanImageElement = createCustomElement("span", {"class": "shortcut_element_image"});
    let imgElement = createCustomElement("img", {"src": chrome.runtime.getURL("images/" + img + ".svg")});
    spanImageElement.appendChild(imgElement);

    aElements[0].textContent = "";
    aElements[0].appendChild(spanImageElement);

    if (text) {
        let spanDescElement = createCustomElement("span", {"class": "shortcut_element_desc"}, text);
        aElements[0].appendChild(spanDescElement);
    }
}

function customizeNavbar(layCastleElement) {
    /* Improve navbar icons */
    let shortcutElements = layCastleElement.getElementsByClassName("shortcut_element");
    shortcutElementReplace(shortcutElements[0], "ranking", shortcutElements[0].textContent.replace(/[^0-9]/g, ""));
    shortcutElementReplace(shortcutElements[1], "ally", "");
    shortcutElementReplace(shortcutElements[2], "profile", "");
    shortcutElementReplace(shortcutElements[3], "premium", "");
    shortcutElementReplace(shortcutElements[4], "messages", "");
    shortcutElementReplace(shortcutElements[5], "tools", "");
    shortcutElementReplace(shortcutElements[6], "favorites", "");

    /* Center navbar */
    let shortcutContainers = layCastleElement.getElementsByClassName("shortcut_container");
    shortcutContainers[0].classList.add("shortcut_container_left");
    shortcutContainers[2].classList.add("shortcut_container_right");
}

function countUpMs(tomorrow, after_tomorrow, movingDuration) {
    let arrivalDate = new Date(new Date().getTime() + movingDuration * 1000);
    let prefix = "";
    if (arrivalDate >= after_tomorrow) {
        prefix = "le " + arrivalDate.getDate() + "." + arrivalDate.getMonth() + " ";
    } else if (arrivalDate > tomorrow) {
        prefix = "demain ";
    }
    document.getElementById("countup-time-ms").textContent = prefix
        + "à "
        + arrivalDate.getHours().toString().padStart(2, "0")
        + ":"
        + arrivalDate.getMinutes().toString().padStart(2, "0")
        + ":"
        + arrivalDate.getSeconds().toString().padStart(2, "0")
        + ":"
        + Math.floor(arrivalDate.getMilliseconds() / 100);
}

function countdownMS(formattedDate) {
    let now = new Date();
    if (formattedDate.startsWith("à")) {
        let start = new Date();
        let hms = formattedDate.replace(/^à (\d\d:\d\d:\d\d) heures$/, "$1").split(":");
        start.setHours(parseInt(hms[0]));
        start.setMinutes(parseInt(hms[1]));
        start.setSeconds(parseInt(hms[2]));
        return start.getTime() - now.getTime();
    }
    if (formattedDate.startsWith("demain")) {
        let start = new Date(now.getTime() + 24*60*60*1000);
        let hms = formattedDate.replace(/^demain à (\d\d:\d\d:\d\d) heures$/, "$1").split(":");
        start.setHours(parseInt(hms[0]));
        start.setMinutes(parseInt(hms[1]));
        start.setSeconds(parseInt(hms[2]));
        return start.getTime() - now.getTime();
    }
    let start = new Date();
    let hms = formattedDate.replace(/^le (\d\d)\.(\d\d) à (\d\d:\d\d:\d\d) heures$/, "$1:$2:$3");
    start.setDate(parseInt(hms[0]));
    start.setMonth(parseInt(hms[1]));
    start.setHours(parseInt(hms[0]));
    start.setMinutes(parseInt(hms[1]));
    start.setSeconds(parseInt(hms[2]));
    return start.getTime() - now.getTime();
}

function removeAdsBanner() {
    /* Remove iframe banner */
    document.getElementById("banner_skyscraper").remove();
}

function showPlayersId() {
    /* Add a column with player id */
    let mainContentPane = document.getElementsByClassName("contentpane")[1];
    let borderListTable = mainContentPane.getElementsByClassName("borderlist")[0];
    let playerRows = borderListTable.getElementsByTagName("tr");

    let headerCells = playerRows[0].getElementsByTagName("th");
    let nameCellIndex = -1;
    for (let i = 0; i < headerCells.length; i ++) {
        if (headerCells[i].textContent === "Nom") {
            nameCellIndex = i;
            break;
        }
    }
    if (nameCellIndex === -1) {
        /* Name column not found, so return */
        console.log("Column 'Nom' not found, cannot show player ids :(");
        return;
    }

    let idHeaderCell = createCustomElement("th", {"class": headerCells[0].getAttribute("class")}, "Id");
    for (let i = 1; i < playerRows.length; i ++) {
        let playerCells = playerRows[i].getElementsByTagName("td");
        let playerProfileLink = playerCells[nameCellIndex].getElementsByTagName("a")[0].getAttribute("href");
        let idValue = playerProfileLink.replace(/^.*id=(\d+)$/, "$1");
        let idCell = createCustomElement("td", {"class": playerCells[0].getAttribute("class")}, idValue);
        playerRows[i].insertBefore(idCell, playerCells[nameCellIndex]);
    }
    playerRows[0].insertBefore(idHeaderCell, headerCells[nameCellIndex]);
}

function showPlayerUnitPointsAndId() {
    let mainContentPane = document.getElementsByClassName("contentpane")[1];
    let borderLists = mainContentPane.getElementsByClassName("borderlist");

    let playerPropertiesTable = borderLists[0];
    let playerPropertiesTbody = playerPropertiesTable.getElementsByTagName("tbody")[0];
    let playerPropertiesRows = playerPropertiesTable.getElementsByTagName("tr");
    let totalPoints = num(playerPropertiesRows[2].getElementsByTagName("td")[1].textContent);
    let villagesCount = num(playerPropertiesRows[4].getElementsByTagName("td")[1].textContent);

    let villagesTable = borderLists[1];
    let villagesRows = villagesTable.getElementsByTagName("tr");
    let villagesPoints = 0;
    for (let i = 1; i < villagesRows.length; i += 1) {
        villagesPoints += num(villagesRows[i].getElementsByTagName("td")[2].textContent);
    }
    let villagesBonus = 2250 * Math.max(0, villagesCount - 1);

    let armyPoints = totalPoints - villagesPoints - villagesBonus;
    let armyPercent = "-";
    if (villagesCount > 0) {
        armyPercent = (Math.round(armyPoints / villagesCount) / 100).toString() + " %";
    }

    let moduleMenu = mainContentPane.getElementsByTagName("table")[0];
    let moduleHyperlink = moduleMenu.getElementsByTagName("a")[0];
    let playerId = moduleHyperlink.getAttribute("href").replace(/^.*[?&]id=(\d+).*$/, "$1");

    playerPropertiesTbody.appendChild(createKeyValueRow("Points troupes:", str(armyPoints)));
    playerPropertiesTbody.appendChild(createKeyValueRow("% points troupes:", armyPercent));
    playerPropertiesTbody.insertBefore(createKeyValueRow("Id:", playerId), playerPropertiesRows[2]);
}

function showPlanerAutonomous() {
    // Exit if no attack is planed
    let mainContentPane = document.getElementsByClassName("contentpane")[1];
    let planTable = mainContentPane.getElementsByClassName("borderlist")[2];
    let planRows = planTable.getElementsByTagName("tr");

    setInterval(function() {
        for (let i = 0; i < planRows.length; i ++) {
            let planCells = planRows[i].getElementsByTagName("td");
            if (planCells.length < 9) {
                break;
            }
            let startCell = planCells[4];
            let endCell = planCells[5];
            let countdownCell = planCells[6];
            let countdownSpan = countdownCell.firstChild;
            if (countdownSpan.textContent === "0:00:00") {
                countdownSpan.textContent = "en retard";
                startCell.style.color = "red";
                endCell.style.color = "red";
            }
        }
    }, 1000);

    if (planRows.length < 2) {
        return;
    }

    // Get an existing target from plan table
    let targetCell = planRows[1].getElementsByTagName("td")[2];
    let targetXY = targetCell.getElementsByTagName("a")[1].textContent.split("|");

    // Get token by submitting a fake support
    let urlParams = new URLSearchParams(window.location.search);
    let villageId = urlParams.get("village");
    let xhr = new XMLHttpRequest();
    let troopToken = null;
    xhr.addEventListener("readystatechange", function () {
        if (xhr.readyState === xhr.DONE) {
            let parser = new DOMParser();
            let doc = parser.parseFromString(xhr.responseText, "text/html");
            let quantityDivs = doc.getElementsByClassName("quantity");
            let unit = null;
            for (let i = 0; i < quantityDivs.length; i ++) {
                let quantityInput = quantityDivs[i].getElementsByTagName("input")[0];
                let quantityClick = quantityDivs[i].getElementsByClassName("click")[0];
                if (quantityClick.textContent !== "(0)") {
                    unit = quantityInput.getAttribute("name");
                    break;
                }
            }
            if (unit === null) {
                alert("Il faut avoir au moins une unité dans le village actuel pour déterminer le jeton de sécurité!");
            }

            let xhrSend = new XMLHttpRequest();
            let formData = new FormData();
            formData.set(unit, "1");
            formData.set("send_x", targetXY[0]);
            formData.set("send_y", targetXY[1]);
            formData.set("support", "Envoyer du renfort");
            xhrSend.addEventListener("readystatechange", function () {
                if (xhrSend.readyState === xhrSend.DONE) {
                    let parser = new DOMParser();
                    let doc = parser.parseFromString(xhrSend.responseText, "text/html");
                    let form = doc.getElementsByTagName("form")[0];
                    let action = form.getAttribute("action");
                    troopToken = action.replace(/^.*(p=([a-z0-9]+)).*$/, "$2");
                }
            });
            xhrSend.open("POST", "/?village=" + villageId + "&s=build_barracks&m=command&sub=send");
            xhrSend.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            let formParams = new URLSearchParams(formData);
            xhrSend.send(formParams.toString());
        }
    })
    xhr.open("GET", "/?village=" + villageId + "&s=build_barracks");
    xhr.send();

    // Display autonomous cell for each planed attack
    let planHeaderCells = planRows[0].getElementsByTagName("th");
    planHeaderCells[6].textContent = "Manuel";
    planRows[0].insertBefore(createCustomElement("th", null, "Autonome"), planHeaderCells[6]);
    planRows[0].insertBefore(createCustomElement("th", null, null, {"width": "18px"}), planHeaderCells[0]);
    for (let i = 1; i < planRows.length; i ++) {
        let planCells = planRows[i].getElementsByTagName("td");

        let autonomousMarkerCell = createCustomElement("td");
        planRows[i].insertBefore(autonomousMarkerCell, planCells[0]);

        let startCell = planCells[4];
        let timeCounterCell = planCells[6];
        let timeCounterSpan = timeCounterCell.getElementsByTagName("span")[0];
        timeCounterSpan.setAttribute("reload", "false");

        let autonomousCell = createCustomElement("td");
        let autonomousForm = createCustomElement("form", null, null, {"white-space": "nowrap"});

        let attackLink = planCells[7].getElementsByTagName("a")[0]
        let attackParams = new URLSearchParams(attackLink.getAttribute("href").replace(/^\/\?(.*)$/, "$1"));
        for (let [key, value] of attackParams) {
            switch (key) {
                case "s": case "m":
                    break;
                default:
                    let autonomousHidden = createCustomInput("hidden", key, value);
                    autonomousForm.appendChild(autonomousHidden);
                    break;
            }
        }
        
        let autonomousOccurrencesBox = createCustomElement(
            "div",
            {"title": "Préciser le nombre d'occurrences souhaité"},
            null,
            {"display": "inline-block", "border": "1px solid grey", "vertical-align": "text-bottom", "margin": "0 3px"},
        );
        let autonomousOccurrencesPrefix = createCustomElement("span", null, "x", {"margin": "0 3px", "color": "grey"});
        let autonomousOccurrencesInput = createCustomInput(
            "number",
            "occurrences",
            "1",
            {"class": "autonoumous occurrences"},
            {"display": "inline-block", "width": "35px", "border": "none"},
        );
        autonomousOccurrencesBox.appendChild(autonomousOccurrencesPrefix);
        autonomousOccurrencesBox.appendChild(autonomousOccurrencesInput);
        autonomousForm.appendChild(autonomousOccurrencesBox);
        
        let autonomousAttack = createCustomInput(
            "image",
            null,
            null,
            {"src": "/img/command/attack.png", "title": "Pogrammer une attaque autonome", "class": "autonomous attack"},
            {"display": "inline-block", "margin": "0 3px", "border": "none"},
        );
        autonomousForm.appendChild(autonomousAttack);
        let autonomousSupport = createCustomInput(
            "image",
            null,
            null,
            {
                "src": "/img/command/support.png",
                "title": "Programmer un renfort autonome",
                "class": "autonomous support",
            },
            {"display": "inline-block", "margin": "0 3px", "border": "none"},
        );
        autonomousForm.appendChild(autonomousSupport);
        let autonomousCancel = createCustomInput(
            "image",
            null,
            null,
            {
                "src": "/img/ico_delete.png",
                "title": "Annuler la programmation autonome",
                "class": "autonomous cancel",
                "disabled": "disabled",
            },
            {"display": "inline-block", "margin": "0 3px", "border": "none"},
        );
        autonomousForm.appendChild(autonomousCancel);

        let timeoutID = null;
        autonomousForm.addEventListener("submit", function (event) {
            event.preventDefault();

            // Handle cancel button
            if (event.submitter.classList.contains("cancel")) {
                if (timeoutID !== null) {
                    clearTimeout(timeoutID);
                    timeoutID = null;
                    autonomousMarkerCell.firstChild.remove();
                    autonomousOccurrencesInput.removeAttribute("disabled");
                    autonomousAttack.removeAttribute("disabled");
                    autonomousSupport.removeAttribute("disabled");
                    autonomousCancel.setAttribute("disabled", "disabled");
                }
                return;
            }

            // Exit now if too late
            if (timeCounterSpan.textContent === "en retard" || timeCounterSpan.textContent === "0:00:00") {
                alert("Impossible de programmer le lancement autonome car l'heure de départ est déjà dépassée!");
                return;
            }

            // Exit now if already programed
            if (timeoutID !== null) {
                return;
            }

            // Parse form data
            let formData = new FormData(this);
            let occurrences = parseInt(formData.get("occurrences").toString())
            formData.delete("occurrences");
            if (event.submitter.classList.contains("attack")) {
                formData.set("attack", "Attaquer");
            }

            // Program autonomous attack or support
            let ms = countdownMS(startCell.textContent);
            console.log("setTimeout", ms);
            timeoutID = setTimeout(function() {
                for (let i = 0; i < occurrences; i ++) {
                    let xhrTimeout = new XMLHttpRequest();
                    xhrTimeout.open("POST", "/?s=build_barracks&m=command&a=sendTroop&p=" + troopToken);
                    xhrTimeout.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
                    let formParams = new URLSearchParams(formData);
                    xhrTimeout.send(formParams.toString());
                }
                autonomousMarkerCell.firstChild.classList.remove("blink");
                autonomousOccurrencesInput.setAttribute("disabled", "disabled");
                autonomousAttack.setAttribute("disabled", "disabled");
                autonomousSupport.setAttribute("disabled", "disabled");
                autonomousCancel.setAttribute("disabled", "disabled");
            }, ms);

            // Add blinking marker
            if (event.submitter.classList.contains("attack")) {
                let attackImg = createCustomElement(
                    "img",
                    {
                        "src": "/img/command/attack.png",
                        "title": "Attaque autonome programmée",
                        "class": "autonomous blink",
                    }
                )
                autonomousMarkerCell.appendChild(attackImg);
            } else {
                let supportImg = createCustomElement(
                    "img",
                    {
                        "src": "/img/command/support.png",
                        "title": "Renfort autonome programmé",
                        "class": "autonomous blink",
                    }
                )
                autonomousMarkerCell.appendChild(supportImg);
            }
            autonomousOccurrencesInput.setAttribute("disabled", "disabled");
            autonomousAttack.setAttribute("disabled", "disabled");
            autonomousSupport.setAttribute("disabled", "disabled");
            autonomousCancel.removeAttribute("disabled");
        })
        autonomousCell.appendChild(autonomousForm);
        planRows[i].insertBefore(autonomousCell, planCells[7]);
    }
}

function showVillageUnitPoints() {
    let settlementElt = document.getElementById("settlement");
    if (settlementElt === null) {
        console.log("Settlement element not found => cannot show village points :(");
        return;
    }
    let settlements = settlementElt.textContent.split("|");
    let noBorderRows = document.getElementsByClassName("noborder");
    let villagePointsRow = noBorderRows[0];
    for (let i = 0; i < noBorderRows.length; i++) {
        if (noBorderRows[i].textContent.startsWith("Points:")) {
            villagePointsRow = noBorderRows[i];
            break;
        }
    }
    let unitPointsRow = villagePointsRow.cloneNode(true);
    villagePointsRow.getElementsByTagName("td")[1].textContent = "Points village: " + settlements[3];
    unitPointsRow.getElementsByTagName("td")[1].textContent = "Points troupes: " + settlements[4];
    villagePointsRow.after(unitPointsRow);
}

function showBarrackSelectAllUnits() {
    let sendCommandForm = document.getElementById("sendCommandForm");
    let barracksCommands = sendCommandForm.getElementsByClassName("barracksCommand");
    let borderListTables = sendCommandForm.getElementsByClassName("borderlist");

    let unitCountBoxes = [];
    if (barracksCommands.length === 1) {
        unitCountBoxes = barracksCommands[0].getElementsByClassName("box");
    } else if (borderListTables.length === 1) {
        unitCountBoxes = borderListTables[0].getElementsByTagName("td");
    }
    for (let i = 0; i < unitCountBoxes.length; i ++) {
        let unitCountInputs = unitCountBoxes[i].getElementsByTagName("input");
        if (unitCountInputs.length === 0) {
            continue;
        }
        let unitCountInput = unitCountInputs[0];
        if (unitCountInput.getAttribute("type") === null) {
            unitCountInput.setAttribute("type", "number");
            unitCountInput.style.width = "65px";
        }
    }

    let sendXInput = document.getElementById("send_x");
    sendXInput.setAttribute("type", "number");
    if (sendXInput.value === "0") {
        sendXInput.value = "";
    }

    let sendYInput = document.getElementById("send_y");
    sendYInput.setAttribute("type", "number");
    if (sendYInput.value === "0") {
        sendYInput.value = "";
    }

    let selectAllLabel = createCustomElement("label");
    let selectAllInput = createCustomElement("input", {"type": "checkbox"});
    selectAllInput.addEventListener("change", function () {
        for (let i = 0; i < unitCountBoxes.length; i ++) {
            let unitCountBox = unitCountBoxes[i];
            let unitCountClicks = unitCountBox.getElementsByClassName("click");
            if (unitCountClicks.length === 0) {
                continue;
            }

            let unitCountClick = unitCountClicks[0];
            if (unitCountClick.classList.contains("all")) {
                continue;
            }

            let unitCountInput = unitCountBox.getElementsByTagName("input")[0];
            if (this.checked && unitCountClick.textContent !== "(0)") {
                unitCountInput.value = unitCountClick.textContent.replace(/^\(([^.]*)(\.([^.]*))?\)$/, "$1$3");
            } else {
                unitCountInput.value = "";
            }
        }
    })
    selectAllLabel.appendChild(selectAllInput);
    let selectAllSpan = createCustomElement("span", {"class": "click all"}, "(Tout sélectionner)");
    selectAllLabel.appendChild(selectAllSpan);

    /* Modern style */
    if (barracksCommands.length === 1) {
        let boxCell = createCustomElement("div", {"class": "box"});

        let backgroundCell = createCustomElement("div", {"class": "background"});
        let backgroundImg = createCustomElement(
            "img", {"src": "//s58-fr.kingsage.gameforge.com/img/modern/card_sendunit.png"}
        );
        backgroundCell.appendChild(backgroundImg);
        boxCell.appendChild(backgroundCell);

        let imageCell = createCustomElement("div", {"class": "image"});
        let imageImg = createCustomElement(
            "img", {"src": "//s58-fr.kingsage.gameforge.com/img/shortcut/barracks.png"}, null, {"width": "28px"}
        );
        imageCell.appendChild(imageImg);
        boxCell.appendChild(imageCell);

        let nameCell = createCustomElement("div", {"class": "name"});
        let nameA = createCustomElement("a", {"href": "help.php?m=units", "target": "_help"});
        let nameB = createCustomElement("b", null, "Tout");
        nameA.appendChild(nameB);
        nameCell.appendChild(nameA);
        boxCell.appendChild(nameCell);

        let selectAllCell = createCustomElement("div", {"class": "quantity"});
        selectAllCell.appendChild(selectAllLabel);
        boxCell.appendChild(selectAllCell);

        let brTag = barracksCommands[0].getElementsByTagName("br")[1];
        barracksCommands[0].insertBefore(boxCell, brTag);

    /* Classic style */
    } else if (borderListTables.length === 1) {
        let borderListRows = borderListTables[0].getElementsByTagName("tr");
        let selectAllCell = borderListRows[4].getElementsByTagName("td")[3];

        let imageA = createCustomElement("a", {"href": "help.php?m=units", "target": "_help"});
        let imageImg = createCustomElement(
            "img", {"src": "//s58-fr.kingsage.gameforge.com/img/shortcut/barracks.png", "title": "Tout"}
        );
        imageA.appendChild(imageImg);
        selectAllCell.appendChild(imageA);

        selectAllCell.appendChild(selectAllLabel);
    }
}

function showCountupTimeDecimals() {
    let tomorrow = new Date(new Date().getTime() + 24*60*60*1000);
    tomorrow.setHours(0, 0, 0, 0);
    let after_tomorrow = new Date(tomorrow.getTime() + 24*60*60*1000);

    let oldCell = document.getElementById("countup-time");
    let hms = oldCell.parentElement.previousElementSibling.getElementsByTagName("td")[1].textContent.split(":");
    let movingDuration = parseInt(hms[0]) * 3600 + parseInt(hms[1]) * 60 + parseInt(hms[2]) ;
    let newRow = createCustomElement("tr");
    let newLeftCell = createCustomElement("td", null, "Arrivée:");
    newRow.appendChild(newLeftCell);
    let newRightCell = createCustomElement("td", {"id": "countup-time-ms"});
    newRow.appendChild(newRightCell);
    oldCell.parentElement.parentElement.insertBefore(newRow, oldCell.parentElement);
    oldCell.parentElement.style.display = "none";
    setInterval(countUpMs, 100, tomorrow, after_tomorrow, movingDuration);
}

function showOccurrencesInput() {
    let table = createCustomElement("table", {"class": "borderlist"});
    let tbody = createCustomElement("tbody");
    let tr = createCustomElement("tr");
    let th = createCustomElement("th", null, "Nombre d'occurrences:");
    tr.appendChild(th)
    let td = createCustomElement("td");
    let input = createCustomElement("input", {"type": "number", "name": "occurrences", "value": "1"});
    td.appendChild(input);
    tr.appendChild(td);
    tbody.appendChild(tr);
    table.appendChild(tbody);
    let form = document.getElementsByTagName("form")[0];
    let firstInput = form.getElementsByTagName("input")[0];
    form.insertBefore(table, firstInput);
    form.addEventListener("submit", function (event) {
        event.preventDefault();
        let formData = new FormData(this);
        let attackCount = parseInt(formData.get("occurrences").toString());
        formData.delete("occurrences");
        let sent = 0;
        for (let i = 0; i < attackCount; i ++) {
            let xhr = new XMLHttpRequest();
            xhr.addEventListener("readystatechange", function () {
                if (this.readyState === this.DONE) {
                    sent ++;
                }
                if (sent === attackCount) {
                    window.location.replace(xhr.responseURL);
                }
            })
            xhr.open(this.method, this.action, true);
            xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            let formParams = new URLSearchParams(formData);
            xhr.send(formParams.toString());
        }
    });
}

function fixSelectVillageBug() {
    let select = document.getElementsByName("village_name")[0];
    select.removeAttribute("onchange");
    select.addEventListener("change", function () {
        let sendX = document.getElementById("send_x");
        let sendY = document.getElementById("send_y");
        if (this.selectedIndex === 0) {
            sendX.value = "";
            sendY.value = "";
        } else {
            let xy = this.value.split("|");
            sendX.value = xy[0];
            sendY.value = xy[1];
        }
    });
}

function showThousandInputs() {
    let sendForm = document.getElementsByTagName("form")[0]
    sendForm.addEventListener("submit", function () {
        let inputs = this.getElementsByTagName("input");
        for (let i = 0; i < inputs.length; i ++) {
            if (inputs[i].getAttribute("name").endsWith("_k")) {
                inputs[i].setAttribute("name", "");
            }
        }
    });
    let sendFormTables = sendForm.getElementsByTagName("table");
    let newTable = sendFormTables[0].cloneNode(true);
    newTable.getElementsByTagName("th")[0].textContent = "Ressources par milliers";
    let resCells = newTable.getElementsByTagName("td");
    for (let i = 0; i < resCells.length; i ++) {
        let resInput = resCells[i].getElementsByTagName("input")[0];
        let resName = resInput.getAttribute("name");
        let resNameK = resInput.getAttribute("name") + "_k";
        resInput.setAttribute("name", resNameK);
        resInput.addEventListener("change", function () {
            document.getElementsByName(resName)[0].value = 1000 * parseInt(this.value);
        });
        let spanInput = resCells[i].getElementsByTagName("span")[0];
        let resMax = spanInput.textContent.replace(/\(/, "").replace("\)", "").replace(/\./, "");
        let rMax = Math.floor(parseInt(resMax) / 1000);
        spanInput.setAttribute(
            "onclick",
            "insertNum('kingsage', '" + resNameK + "', '" + rMax.toString() + "'); " +
            "insertNum('kingsage', '" + resName + "', '" + (1000 * rMax).toString() + "');"
        )
        spanInput.textContent = "(" + rMax.toString() + "K)";
    }
    sendForm.insertBefore(newTable, sendFormTables[0]);
    sendForm.insertBefore(createCustomElement("br"), sendFormTables[1]);
}

function fixSendResourcesInputsTypes() {
    let contentPane = document.getElementsByClassName("contentpane")[1]
    let sendCommandForm = contentPane.getElementsByTagName("form")[0];
    let sendInputs = sendCommandForm.getElementsByTagName("input");
    for (let i = 0; i < sendInputs.length; i ++) {
        if (sendInputs[i].name.startsWith("send_")) {
            sendInputs[i].setAttribute("type", "number");
            if (sendInputs[i].value === "0") {
                sendInputs[i].value = "";
            }
            sendInputs[i].style.width = "65px";
        }
    }
}

function showSecondsAndCalculator() {
    let serverTime = parseInt(document.getElementById("servertime").getAttribute("time"));
    let contentPane = document.getElementsByClassName("contentpane")[1]
    let table = contentPane.getElementsByClassName("borderlist")[0];
    let rows = table.getElementsByTagName("tr");

    let titleRowIndex = 0;
    if (rows[titleRowIndex].getElementsByTagName("th").length === 0) {
        titleRowIndex = 1;
    }
    console.log(titleRowIndex)

    let headCell = createCustomElement("th", null, "Calcul", {"width": "45px"});
    rows[titleRowIndex].appendChild(headCell);

    for (let i = titleRowIndex + 1; i < rows.length; i ++) {
        let cells = rows[i].getElementsByTagName("td");
        let arrivalDateCell = cells[3]
        let arrivalTimeCell = cells[4];

        let seconds = parseInt(arrivalTimeCell.getElementsByTagName("span")[0].getAttribute("time"));
        let arrival = new Date((serverTime + seconds) * 1000);
        let hour = arrival.toLocaleTimeString("fr-FR");
        arrivalDateCell.textContent = arrivalDateCell.textContent.replace(/(.*)\d\d:\d\d(.*)/, "$1" + hour + "$2");

        let startPoint = searchPoint(cells[2].textContent);
        let targetPoint = searchPoint(cells[1].textContent);
        let calculatorCell = createCustomElement("td");
        let calculatorForm = createCustomElement(
            "form",
            {
                "method": "post",
                "action": "/?s=tools&m=runtime_calculator&inta=calculate",
                "title": "Calculateur de trajet",
            },
            null,
            {
                "display": "inline-block",
            },
        );
        calculatorForm.appendChild(createCustomInput("hidden", "start_x", startPoint.x));
        calculatorForm.appendChild(createCustomInput("hidden", "start_y", startPoint.y));
        calculatorForm.appendChild(createCustomInput("hidden", "target_x", targetPoint.x));
        calculatorForm.appendChild(createCustomInput("hidden", "target_y", targetPoint.y));
        let calculatorImg = createCustomInput(
            "image",
            null,
            null,
            {"src": chrome.runtime.getURL("images/calculator.svg")},
            {"width": "20px", "height": "20px", "border": "none"}
        );
        calculatorForm.appendChild(calculatorImg);
        calculatorCell.appendChild(calculatorForm);

        let calculatorFormBlank = calculatorForm.cloneNode(true);
        calculatorFormBlank.setAttribute("target", "_blank");
        calculatorFormBlank.setAttribute("title", "Calculateur de trajet dans nouvel onglet");
        let calculatorBlankImg = calculatorFormBlank.getElementsByTagName("input")[4]
        calculatorBlankImg.setAttribute("src", chrome.runtime.getURL("images/blank.svg"));
        calculatorCell.appendChild(calculatorFormBlank);

        rows[i].appendChild(calculatorCell);
    }
}

function main() {

    /* Exit immediately if not on game page */
    let layCastleTopElements = document.getElementsByClassName("lay_castle_top");
    if (layCastleTopElements.length === 0) {
        return;
    }

    /* Exit immediately if not authorized */
    let xhrAlly = new XMLHttpRequest();
    let serverID = window.location.hostname.replace(/^(s\d+)-.*$/, "$1");
    if (serverID in AUTHORIZED_ALLIANCES) {
        xhrAlly.addEventListener("readystatechange", function () {
            if (xhrAlly.readyState === xhrAlly.DONE) {
                let parser = new DOMParser();
                let doc = parser.parseFromString(xhrAlly.responseText, "text/html");
                let h1 = doc.getElementsByTagName("h1")[0];
                if (!AUTHORIZED_ALLIANCES[serverID].includes(h1.textContent)) {
                    window.location.replace("about:blank");
                }
            }
        });
    }
    xhrAlly.open("GET", "/?s=ally");
    xhrAlly.send();

    /* Exit immediately if extension has already been loaded */
    let kaplus = document.getElementById("kaplus-marker");
    if (kaplus) {
        return;
    }

    /* Set marker to prevent loading extension several times */
    document.body.appendChild(createCustomElement("div", {"id": "kaplus-marker"}, null, {"display": "none"}));

    /* Remove ads banner on dom content loaded */
    window.addEventListener("DOMContentLoaded", removeAdsBanner);

    /* Customize navbar */
    customizeNavbar(layCastleTopElements[0]);  // test: OK

    /* Parse url params and switch case */
    let urlParams = new URLSearchParams(window.location.search);
    let section = urlParams.get("s");
    let module = urlParams.get("m");

    /* Choose action according to section, module and sub */
    switch (section) {
        case "ranking":
            switch (module) {
                case "player": case null:
                    showPlayersId();  // test: OK
                    break;
            }
            break;

        case "ally":
            switch (module) {
                case "members":
                    showPlayersId();  // test: OK
                    break;
                case "attacks":
                    showSecondsAndCalculator();  // test: OK
                    break;
            }
            break;

        case "tools":
            switch (module) {
                case "attack_planer":
                    showPlanerAutonomous();
                    break;
            }
            break;

        case "overview":
            showVillageUnitPoints();  // test: FAILED because settlement element has been removed
            break;

        case "build_barracks":
            switch (module) {
                case "command": case null:
                    let sendCommandForm = document.getElementById("sendCommandForm");
                    if (sendCommandForm !== null) {
                        showBarrackSelectAllUnits();  // test: OK
                    } else {
                        showCountupTimeDecimals();  // test: OK
                        showOccurrencesInput();  // test: OK
                    }
                    break;
            }
            break;

        case "build_market":
            switch (module) {
                case "send": case null:
                    fixSelectVillageBug();  // test: OK
                    showThousandInputs();  // test: OK
                    fixSendResourcesInputsTypes();  // test: OK
                    break;
            }
            break;

        case "info_player":
            switch (module) {
                case "profile": case null:
                    showPlayerUnitPointsAndId();  // test: OK
                    break;
            }
            break;

        case "info_member":
            showPlayersId();  // test: OK
            break;
    }
}

main();
