package de.steamwar.bausystem.features.bau;

import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.config.BauServer;
import de.steamwar.bausystem.region.Region;
import de.steamwar.bausystem.region.flags.Flag;
import de.steamwar.command.SWCommand;
import de.steamwar.core.TPSWatcher;
import de.steamwar.linkage.Linked;
import de.steamwar.linkage.LinkedInstance;
import de.steamwar.sql.BauweltMember;
import de.steamwar.sql.SteamwarUser;
import org.bukkit.entity.Player;

import java.util.*;

@Linked
public class InfoCommand extends SWCommand {

    @LinkedInstance
    public BauServer bauServer;

    public InfoCommand() {
        super("bauinfo");
    }

    @Register(description = "BAU_INFO_COMMAND_HELP")
    public void genericCommand(Player p) {
        BauSystem.MESSAGE.send("BAU_INFO_COMMAND_OWNER", p, SteamwarUser.get(bauServer.getOwnerID()).getUserName());
        Region region = Region.getRegion(p.getLocation());
        for (Flag flag : Flag.getFlags()) {
            if (flag == Flag.PROTECT && region.getFloorLevel() == 0) {
                continue;
            }
            Flag.Value<?> value = region.get(flag);
            if (value != null) {
                BauSystem.MESSAGE.send("BAU_INFO_COMMAND_FLAG", p, BauSystem.MESSAGE.parse(flag.getChatValue(), p), BauSystem.MESSAGE.parse(value.getChatValue(), p));
            }
        }

        if (Permission.BUILD.hasPermission(p)) {
            List<BauweltMember> members = BauweltMember.getMembers(bauServer.getOwnerID());
            Map<Permission, List<BauweltMember>> memberByPermission = new HashMap<>();
            members.forEach(member -> {
                if (Permission.SUPERVISOR.hasPermission(member)) {
                    memberByPermission.computeIfAbsent(Permission.SUPERVISOR, __ -> new ArrayList<>()).add(member);
                } else if (Permission.BUILD.hasPermission(member)) {
                    memberByPermission.computeIfAbsent(Permission.BUILD, __ -> new ArrayList<>()).add(member);
                } else {
                    memberByPermission.computeIfAbsent(Permission.MEMBER, __ -> new ArrayList<>()).add(member);
                }
            });

            List<BauweltMember> supervisor = memberByPermission.getOrDefault(Permission.SUPERVISOR, Collections.emptyList());
            BauSystem.MESSAGE.send("BAU_INFO_COMMAND_MEMBER", p, "§eSupervisor", supervisor.size(), supervisor.isEmpty() ? "§8<none>" : joining(supervisor));

            List<BauweltMember> builder = memberByPermission.getOrDefault(Permission.BUILD, Collections.emptyList());
            BauSystem.MESSAGE.send("BAU_INFO_COMMAND_MEMBER", p, "§6Builder", builder.size(), builder.isEmpty() ? "§8<none>" : joining(builder));

            List<BauweltMember> spectator = memberByPermission.getOrDefault(Permission.MEMBER, Collections.emptyList());
            BauSystem.MESSAGE.send("BAU_INFO_COMMAND_MEMBER", p, "§7Spectator", spectator.size(), spectator.isEmpty() ? "§8<none>" : joining(spectator));
        }

        StringBuilder tpsMessage = new StringBuilder();
        tpsMessage.append(BauSystem.MESSAGE.parsePrefixed("BAU_INFO_COMMAND_TPS", p));
        tpsMessage.append(" ").append(TPSWatcher.getTPS(TPSWatcher.TPSType.ONE_SECOND));
        tpsMessage.append(" ").append(TPSWatcher.getTPS(TPSWatcher.TPSType.TEN_SECONDS));
        tpsMessage.append(" ").append(TPSWatcher.getTPS(TPSWatcher.TPSType.ONE_MINUTE));
        tpsMessage.append(" ").append(TPSWatcher.getTPS(TPSWatcher.TPSType.FIVE_MINUTES));
        tpsMessage.append(" ").append(TPSWatcher.getTPS(TPSWatcher.TPSType.TEN_MINUTES));
        p.sendMessage(tpsMessage.toString());
    }

    private String joining(List<BauweltMember> bauweltMembers) {
        StringBuilder st = new StringBuilder();
        for (int i = 0; i < bauweltMembers.size(); i++) {
            if (i != 0) {
                st.append("§8, ");
            }
            st.append("§7");
            st.append(SteamwarUser.get(bauweltMembers.get(i).getMemberID()).getUserName());
        }
        return st.toString();
    }
}
