package eu.mhsl.minecraft.endlessjumper;

import eu.mhsl.minecraft.endlessjumper.generator.JumpGenerator;
import net.minestom.server.MinecraftServer;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.entity.Player;
import net.minestom.server.entity.PlayerSkin;
import net.minestom.server.event.GlobalEventHandler;
import net.minestom.server.event.player.AsyncPlayerConfigurationEvent;
import net.minestom.server.event.player.PlayerDisconnectEvent;
import net.minestom.server.event.player.PlayerMoveEvent;
import net.minestom.server.extras.velocity.VelocityProxy;
import net.minestom.server.instance.InstanceContainer;
import net.minestom.server.instance.InstanceManager;
import net.minestom.server.instance.block.Block;
import net.minestom.server.timer.TaskSchedule;

import java.util.HashMap;

public class EndlessJumper {
    public static void main(String[] args) {
        MinecraftServer server = MinecraftServer.init();
        InstanceManager instanceManager = MinecraftServer.getInstanceManager();
        GlobalEventHandler eventHandler = MinecraftServer.getGlobalEventHandler();
        PlayerSkin skin = PlayerSkin.fromUsername("Notch");

        HashMap<Player, JumpGenerator> games = new HashMap<>();

        eventHandler.addListener(AsyncPlayerConfigurationEvent.class, event -> {
            final Player p = event.getPlayer();
            p.setRespawnPoint(new Pos(0.5,101.5,0.5));

            final InstanceContainer world = instanceManager.createInstanceContainer();
            world.setGenerator(new TerrainGenerator());

            Pos startingAt = new Pos(0,100,0);
            world.setBlock(startingAt, Block.DIAMOND_BLOCK);

            world.setTimeRate(0);
            world.setTime(18000);

            p.setSkin(skin);

            event.setSpawningInstance(world);

            MinecraftServer.getSchedulerManager().scheduleTask(
                () -> games.put(p, new JumpGenerator(startingAt, p, world)),
                TaskSchedule.seconds(3),
                TaskSchedule.stop()
            );
        });

        eventHandler.addListener(PlayerMoveEvent.class, event -> {
            Player p = event.getPlayer();

            if(!games.containsKey(p)) {
                event.setCancelled(true);
                return;
            }

            JumpGenerator generator = games.get(p);

            //reset when falling down
            if(p.getPosition().y() < generator.getNextLanding().y()-5 && p.getPosition().y() < generator.getCheckpoint().y()) generator.reset();

            Pos p1 = BlockMath.roundToBlock(event.getNewPosition().sub(0.0,1.0,0.0));
            Pos p2 = BlockMath.roundToBlock(event.getNewPosition().sub(0.0, 2.0, 0.0));


            for(int i = 0; i <= generator.getPreview(); i++) {
                Pos target = generator.getBlocks().get(generator.getBlocks().size()-i-1);
                if(p1.sameBlock(target) || p2.sameBlock(target)) generator.generateNext();
            }


            //if(p.getPosition().z() > target.z()+2) generator.highlight();
        });

        eventHandler.addListener(PlayerDisconnectEvent.class, event -> games.remove(event.getPlayer()));

        VelocityProxy.enable("iph0YHK9jNWZ");
        server.start("0.0.0.0", 25501);

    }
}
