import { Player } from "./util/Player.js";
import { P } from './Squaremap.js';

class PlayerList {
    constructor(json) {
        this.players = new Map();
        this.markers = new Map();
        this.following = null;
        this.firstTick = true;
        this.label = json.player_list_label;
        P.map.createPane("nameplate").style.zIndex = 1000;
    }
    tick() {
        if (P.tick_count % P.worldList.curWorld.player_tracker.update_interval == 0) {
            P.getJSON("tiles/players.json", (json) => {
                this.updatePlayerList(json.players);
                const title = `${this.label}`
                    .replace(/{cur}/g, json.players.length)
                    .replace(/{max}/g, json.max == null ? "???" : json.max)
                if (P.sidebar.players.legend.innerHTML !== title) {
                    P.sidebar.players.legend.innerHTML = title;
                }
            });
        }
    }
    showPlayer(uuid) {
        const player = this.players.get(uuid);
        if (!P.worldList.worlds.has(player.world)) {
            return false;
        }
        P.worldList.showWorld(player.world, () => {
            P.map.panTo(P.toLatLng(player.x, player.z));
        });
        return true;
    }
    addToList(player) {
        const head = document.createElement("img");
        head.src = player.getHeadUrl();

        const span = document.createElement("span");
        span.innerHTML = player.displayName

        const link = P.createElement("a", player.uuid, this);
        link.onclick = function (e) {
            if (this.parent.showPlayer(this.id)) {
                this.parent.followPlayerMarker(this.id);
                e.stopPropagation();
            }
        };
        link.appendChild(head);
        link.appendChild(span);
        const fieldset = P.sidebar.players.element;
        fieldset.appendChild(link);
        Array.from(fieldset.getElementsByTagName("a"))
            .sort((a, b) => {
                return plain(a.getElementsByTagName("span")[0])
                    .localeCompare(plain(b.getElementsByTagName("span")[0]));
            })
            .forEach(link => fieldset.appendChild(link));
    }
    removeFromList(player) {
        const link = document.getElementById(player.uuid);
        if (link != null) {
            link.remove();
        }
        this.players.delete(player.uuid);
        player.removeMarker();
    }
    updatePlayerList(players) {
        const playersToRemove = Array.from(this.players.keys());

        let needsSort = false;

        // update players from json
        for (let i = 0; i < players.length; i++) {
            let player = this.players.get(players[i].uuid);
            if (player == null) {
                // new player
                player = new Player(players[i]);
                this.players.set(player.uuid, player);
                this.addToList(player);
            } else {
                const oldDisplayName = player.displayName;
                player.update(players[i]);
                if (oldDisplayName !== player.displayName) {
                    needsSort = true;
                    document.getElementById(player.uuid)
                        .getElementsByTagName("span")[0]
                        .innerHTML = player.displayName;
                }
            }
            playersToRemove.remove(players[i].uuid);
        }

        // remove players not in json
        for (let i = 0; i < playersToRemove.length; i++) {
            const player = this.players.get(playersToRemove[i]);
            this.removeFromList(player);
        }

        if (needsSort) {
            const fieldset = P.sidebar.players.element;
            Array.from(fieldset.getElementsByTagName("a"))
                .sort((a, b) => {
                    return plain(a.getElementsByTagName("span")[0])
                        .localeCompare(plain(b.getElementsByTagName("span")[0]));
                })
                .forEach(link => fieldset.appendChild(link));
        }

        // first tick only
        if (this.firstTick) {
            this.firstTick = false;

            // follow uuid from url
            const follow = P.getUrlParam("uuid", null);
            if (follow != null && this.players.get(follow) != null) {
                this.followPlayerMarker(follow);
            }
        }

        // follow highlighted player
        if (this.following != null) {
            const player = this.players.get(this.following);
            if (player != null && P.worldList.curWorld != null) {
                if (player.world !== P.worldList.curWorld.name) {
                    P.worldList.showWorld(player.world, () => {
                        P.map.panTo(P.toLatLng(player.x, player.z));
                    });
                } else {
                    P.map.panTo(P.toLatLng(player.x, player.z));
                }
            }
        }
    }
    clearPlayerMarkers() {
        const playersToRemove = Array.from(this.players.keys());
        for (let i = 0; i < playersToRemove.length; i++) {
            const player = this.players.get(playersToRemove[i]);
            player.removeMarker();
        }
        this.markers.clear();
        //P.layerControl.playersLayer.clearLayers();
    }
    followPlayerMarker(uuid) {
        if (this.following != null) {
            document.getElementById(this.following).classList.remove("following");
            this.following = null;
        }
        if (uuid != null) {
            this.following = uuid;
            document.getElementById(this.following).classList.add("following");
        }
    }
}

function plain(element) {
    return element.textContent || element.innerText || "";
}

export { PlayerList };
