<?php
namespace HG\HG;

use pocketmine\plugin\PluginBase;
use pocketmine\scheduler\PluginTask;
use pocketmine\event\Listener;
use pocketmine\event\player\PlayerInteractEvent;
use pocketmine\event\player\PlayerLoginEvent;
use pocketmine\event\player\PlayerChatEvent;
use pocketmine\command\CommandSender;
use pocketmine\command\Command;
use pocketmine\utils\TextFormat;
use pocketmine\utils\Config;
use pocketmine\math\Vector3;
use pocketmine\level\Position;
use pocketmine\Player;
use pocketmine\block\Block;
use pocketmine\tile\Sign;
use pocketmine\level\Level;
use pocketmine\item\Item;
use pocketmine\event\block\BlockBreakEvent;
use pocketmine\event\block\BlockPlaceEvent;
use pocketmine\event\player\PlayerMoveEvent;
use pocketmine\event\player\PlayerDeathEvent;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\event\player\PlayerJoinEvent;
use pocketmine\event\player\PlayerQuitEvent;
use pocketmine\entity\Effect;
use pocketmine\tile\Chest;
use pocketmine\inventory\ChestInventory;
use pocketmine\level\sound\AnvilUseSound;
use pocketmine\level\sound\GhastSound;
use HG\HG\ResetMap;
use HG\HG\Mod_TopModule;

class HG extends PluginBase implements Listener
{
    public $prefix = "§8(§2H§fG§8)§f ";

    public $mode = 0;
    public $MOD_top_module;
    public $arenas = array();
    public $currentLevel = "";

    public function onEnable()
    {
        $this->MOD_top_module = new Mod_TopModule($this);
        $this->getLogger()
            ->info(TextFormat::AQUA . "HG Enabled");
        $this->getServer()
            ->getPluginManager()
            ->registerEvents($this, $this);
        @mkdir($this->getDataFolder());
        $config2 = new Config($this->getDataFolder() . "/rank.yml", Config::YAML);
        $config2->save();
        $config = new Config($this->getDataFolder() . "/config.yml", Config::YAML);
        if ($config->get("arenas") != null)
        {
            $this->arenas = $config->get("arenas");
        }
        foreach ($this->arenas as $lev)
        {
            $this->getServer()
                ->loadLevel($lev);
        }
        $items = array(
            array(
                268,
                0,
                1
            ) ,
            array(
                269,
                0,
                1
            ) ,
            array(
                270,
                0,
                1
            ) ,
            array(
                271,
                0,
                1
            ) , // Wooden tools
            array(
                272,
                0,
                1
            ) ,
            array(
                273,
                0,
                1
            ) ,
            array(
                274,
                0,
                1
            ) ,
            array(
                275,
                0,
                1
            ) , // Stone tools
            array(
                267,
                0,
                1
            ) ,
            array(
                256,
                0,
                1
            ) ,
            array(
                257,
                0,
                1
            ) ,
            array(
                258,
                0,
                1
            ) , // Iron tools
            array(
                276,
                0,
                1
            ) ,
            array(
                277,
                0,
                1
            ) ,
            array(
                278,
                0,
                1
            ) ,
            array(
                279,
                0,
                1
            ) , // Diamond tools (rare)
            array(
                261,
                0,
                1
            ) ,
            array(
                262,
                0,
                8
            ) ,
            array(
                262,
                0,
                16
            ) ,
            array(
                262,
                0,
                5
            ) , // Bow & Arrows
            array(
                298,
                0,
                1
            ) ,
            array(
                299,
                0,
                1
            ) ,
            array(
                300,
                0,
                1
            ) ,
            array(
                301,
                0,
                1
            ) , // Leather armor
            array(
                302,
                0,
                1
            ) ,
            array(
                303,
                0,
                1
            ) ,
            array(
                304,
                0,
                1
            ) ,
            array(
                305,
                0,
                1
            ) , // Chain armor
            array(
                306,
                0,
                1
            ) ,
            array(
                307,
                0,
                1
            ) ,
            array(
                308,
                0,
                1
            ) ,
            array(
                309,
                0,
                1
            ) , // Iron armor
            array(
                314,
                0,
                1
            ) ,
            array(
                315,
                0,
                1
            ) ,
            array(
                316,
                0,
                1
            ) ,
            array(
                317,
                0,
                1
            ) , // Gold armor
            array(
                310,
                0,
                1
            ) ,
            array(
                311,
                0,
                1
            ) ,
            array(
                312,
                0,
                1
            ) ,
            array(
                313,
                0,
                1
            ) , // Diamond armor (rare)
            array(
                260,
                0,
                3
            ) ,
            array(
                260,
                0,
                5
            ) ,
            array(
                260,
                0,
                8
            ) , // Apples
            array(
                322,
                0,
                1
            ) ,
            array(
                322,
                0,
                2
            ) , // Golden Apples
            array(
                297,
                0,
                5
            ) ,
            array(
                297,
                0,
                3
            ) , // Bread
            array(
                320,
                0,
                3
            ) ,
            array(
                320,
                0,
                5
            ) , // Cooked Porkchop
            array(
                364,
                0,
                4
            ) ,
            array(
                364,
                0,
                6
            ) , // Cooked Steak
            array(
                366,
                0,
                5
            ) ,
            array(
                366,
                0,
                8
            ) , // Cooked Chicken
            array(
                282,
                0,
                1
            ) ,
            array(
                282,
                0,
                2
            ) , // Mushroom Stew
            array(
                391,
                0,
                5
            ) ,
            array(
                392,
                0,
                5
            ) ,
            array(
                393,
                0,
                3
            ) , // Carrots, Potatoes, Baked Potato
            array(
                280,
                0,
                2
            ) ,
            array(
                280,
                0,
                1
            ) , // Sticks
            array(
                287,
                0,
                3
            ) ,
            array(
                287,
                0,
                5
            ) , // String
            array(
                264,
                0,
                1
            ) ,
            array(
                264,
                0,
                2
            ) , // Diamonds
            array(
                265,
                0,
                3
            ) ,
            array(
                265,
                0,
                5
            ) , // Iron Ingots
            array(
                266,
                0,
                2
            ) ,
            array(
                266,
                0,
                3
            ) , // Gold Ingots
            array(
                263,
                0,
                5
            ) ,
            array(
                263,
                0,
                8
            ) , // Coal
            array(
                368,
                0,
                1
            ) ,
            array(
                368,
                0,
                2
            ) , // Ender Pearls
            array(
                332,
                0,
                8
            ) ,
            array(
                332,
                0,
                16
            ) , // Snowballs
            array(
                344,
                0,
                8
            ) ,
            array(
                344,
                0,
                16
            ) , // Eggs
            array(
                46,
                0,
                2
            ) ,
            array(
                46,
                0,
                3
            ) , // TNT
            array(
                259,
                0,
                1
            ) , // Flint and Steel
            array(
                345,
                0,
                1
            ) , // Compass
            array(
                4,
                0,
                32
            ) ,
            array(
                4,
                0,
                16
            ) , // Cobblestone
            array(
                17,
                0,
                16
            ) ,
            array(
                17,
                0,
                8
            ) // Wood Logs
            
        );
        // Chest items handled in GameSender

        $config->save();
        $statistic = new Config($this->getDataFolder() . "/statistic.yml", Config::YAML);
        $statistic->save();
        $this->getServer()
            ->getScheduler()
            ->scheduleRepeatingTask(new GameSender($this) , 20);
        $this->getServer()
            ->getScheduler()
            ->scheduleRepeatingTask(new RefreshSigns($this) , 10);
        $this->getServer()
            ->getScheduler()
            ->scheduleRepeatingTask(new ScoreboardTask($this) , 20);
    }
    public function onDisable()
    {
        foreach($this->arenas as $name) {
            $zip = new \ZipArchive;
            $zip->open($this->getDataFolder() . 'arenas/' . $name . '.zip');
            $zip->extractTo($this->getServer()->getDataPath() . 'worlds');
            $zip->close();
            unset($zip);
        }
    }
    public function getLeaveItem()
    {
        $item = Item::get(355, 14, 1);
        $item->setCustomName("§c§lLeave Game");
        return $item;
    }

    public function giveRankKit(Player $player)
    {
        $rankConfig = new Config($this->getDataFolder() . "/rank.yml", Config::YAML);
        $playerRank = $rankConfig->get($player->getName());

        if ($playerRank == "Warrior")
        {
            $player->getInventory()
                ->addItem(Item::get(268, 0, 1)); // Wooden Sword
            $player->getInventory()
                ->addItem(Item::get(298, 0, 1)); // Leather Helmet
            $player->getInventory()
                ->addItem(Item::get(260, 0, 3)); // 3 Apples
            $player->addEffect(Effect::getEffect(1)
                ->setDuration(600)
                ->setAmplifier(0)
                ->setVisible(false)); // Speed I 30s
            
        }
        else if ($playerRank == "Deluxe")
        {
            $player->getInventory()
                ->addItem(Item::get(272, 0, 1)); // Stone Sword
            $player->getInventory()
                ->addItem(Item::get(298, 0, 1)); // Leather Helmet
            $player->getInventory()
                ->addItem(Item::get(299, 0, 1)); // Leather Chestplate
            $player->getInventory()
                ->addItem(Item::get(260, 0, 5)); // 5 Apples
            $player->getInventory()
                ->addItem(Item::get(262, 0, 8)); // 8 Arrows
            $player->addEffect(Effect::getEffect(1)
                ->setDuration(800)
                ->setAmplifier(0)
                ->setVisible(false)); // Speed I 40s
            $player->addEffect(Effect::getEffect(11)
                ->setDuration(600)
                ->setAmplifier(0)
                ->setVisible(false)); // Resistance I 30s
            
        }
        else if ($playerRank == "Platinum")
        {
            $player->getInventory()
                ->addItem(Item::get(267, 0, 1)); // Iron Sword
            $player->getInventory()
                ->addItem(Item::get(306, 0, 1)); // Iron Helmet
            $player->getInventory()
                ->addItem(Item::get(299, 0, 1)); // Leather Chestplate
            $player->getInventory()
                ->addItem(Item::get(300, 0, 1)); // Leather Leggings
            $player->getInventory()
                ->addItem(Item::get(260, 0, 8)); // 8 Apples
            $player->getInventory()
                ->addItem(Item::get(261, 0, 1)); // Bow
            $player->getInventory()
                ->addItem(Item::get(262, 0, 12)); // 12 Arrows
            $player->addEffect(Effect::getEffect(1)
                ->setDuration(1200)
                ->setAmplifier(0)
                ->setVisible(false)); // Speed I 60s
            $player->addEffect(Effect::getEffect(11)
                ->setDuration(800)
                ->setAmplifier(0)
                ->setVisible(false)); // Resistance I 40s
            $player->addEffect(Effect::getEffect(10)
                ->setDuration(600)
                ->setAmplifier(0)
                ->setVisible(false)); // Regen I 30s
            
        }
        else if ($playerRank == "Premium")
        {
            $player->getInventory()
                ->addItem(Item::get(276, 0, 1)); // Diamond Sword
            $player->getInventory()
                ->addItem(Item::get(310, 0, 1)); // Diamond Helmet
            $player->getInventory()
                ->addItem(Item::get(307, 0, 1)); // Iron Chestplate
            $player->getInventory()
                ->addItem(Item::get(308, 0, 1)); // Iron Leggings
            $player->getInventory()
                ->addItem(Item::get(309, 0, 1)); // Iron Boots
            $player->getInventory()
                ->addItem(Item::get(322, 0, 2)); // 2 Golden Apples
            $player->getInventory()
                ->addItem(Item::get(261, 0, 1)); // Bow
            $player->getInventory()
                ->addItem(Item::get(262, 0, 16)); // 16 Arrows
            $player->addEffect(Effect::getEffect(1)
                ->setDuration(2400)
                ->setAmplifier(1)
                ->setVisible(false)); // Speed II 2min
            $player->addEffect(Effect::getEffect(11)
                ->setDuration(1200)
                ->setAmplifier(0)
                ->setVisible(false)); // Resistance I 60s
            $player->addEffect(Effect::getEffect(10)
                ->setDuration(1200)
                ->setAmplifier(0)
                ->setVisible(false)); // Regen I 60s
            $player->addEffect(Effect::getEffect(5)
                ->setDuration(1200)
                ->setAmplifier(0)
                ->setVisible(false)); // Strength I 60s
            
        }
    }

    public function applyKnockback(Player $victim, Player $attacker, $force = 0.4)
    {
        $x = $victim->getX() - $attacker->getX();
        $z = $victim->getZ() - $attacker->getZ();
        $f = sqrt($x * $x + $z * $z);
        if ($f <= 0) return;
        $f = 1 / $f;
        $motion = $victim->getMotion();
        $motion->x = $motion->x / 2 + $x * $f * $force;
        $motion->y = $motion->y / 2 + 0.1;
        $motion->z = $motion->z / 2 + $z * $f * $force;
        if ($motion->y > 0.1) $motion->y = 0.1;
        $victim->setMotion($motion);
    }

    public function leaveArena(Player $player)
    {
        $level = $player->getLevel()
            ->getFolderName();
        if (in_array($level, $this->arenas))
        {
            $player->getInventory()
                ->clearAll();
            $player->getInventory()
                ->setHelmet(Item::get(0, 0, 0));
            $player->getInventory()
                ->setChestplate(Item::get(0, 0, 0));
            $player->getInventory()
                ->setLeggings(Item::get(0, 0, 0));
            $player->getInventory()
                ->setBoots(Item::get(0, 0, 0));
            $player->removeAllEffects();
            $player->setHealth(20);
            $player->setFood(20);
            $spawn = $this->getServer()
                ->getDefaultLevel()
                ->getSafeSpawn();
            $this->getServer()
                ->getDefaultLevel()
                ->loadChunk($spawn->getFloorX() , $spawn->getFloorZ());
            $player->teleport($spawn, 0, 0);
            $player->sendMessage($this->prefix . "You left the game.");
            return true;
        }
        return false;
    }

    public function onQuit(PlayerQuitEvent $event)
    {
        $pl = $event->getPlayer();
        $level = $pl->getLevel()
            ->getFolderName();
        if (in_array($level, $this->arenas))
        {
            $pl->removeAllEffects();
            $pl->getInventory()
                ->clearAll();
            $pl->getInventory()
                ->setHelmet(Item::get(0, 0, 0));
            $pl->getInventory()
                ->setChestplate(Item::get(0, 0, 0));
            $pl->getInventory()
                ->setLeggings(Item::get(0, 0, 0));
            $pl->getInventory()
                ->setBoots(Item::get(0, 0, 0));
            $pl->setFood(20);
            $pl->setMaxHealth(20);
            $pl->setHealth(20);
        }
    }

    public function onDeath(PlayerDeathEvent $event)
    {
        $jugador = $event->getEntity();
        $level = $jugador->getLevel();
        $cause = $jugador->getLastDamageCause();
        $spawn = $this->getServer()
            ->getDefaultLevel()
            ->getSafeSpawn();
        $jugador->teleport($spawn, 0, 0);
        $jugador->getInventory()
            ->clearAll();
        $jugador->removeAllEffects();
        if (!($cause instanceof EntityDamageByEntityEvent)) return;
        $asassin = ($cause->getDamager() instanceof Player ? $cause->getDamager() : false);
        if ($asassin !== false)
        {
            $event->setDeathMessage("");
            foreach ($level->getPlayers() as $pl)
            {
                $muerto = $jugador->getName();
                $asesino = $asassin->getName();
                $pl->sendMessage(TextFormat::RED . "§f" . $muerto . " §7was killed by " . "§c" . $asesino);
            }
        }
    }

    public function onMove(PlayerMoveEvent $event)
    {
        $player = $event->getPlayer();
        $level = $player->getLevel()
            ->getFolderName();
        if (in_array($level, $this->arenas))
        {
            $config = new Config($this->getDataFolder() . "/config.yml", Config::YAML);
            $sofar = $config->get($level . "StartTime");
            if ($sofar > 0)
            {
                $to = clone $event->getFrom();
                $to->yaw = $event->getTo()->yaw;
                $to->pitch = $event->getTo()->pitch;
                $event->setTo($to);
            }
        }
    }

    public function onBlockBreak(BlockBreakEvent $event)
    {
        $player = $event->getPlayer();
        $level = $player->getLevel()
            ->getFolderName();
        if (in_array($level, $this->arenas))
        {
            $config = new Config($this->getDataFolder() . "/config.yml", Config::YAML);
            if ($config->get($level . "PlayTime") != null)
            {
                if ($config->get($level . "PlayTime") >= 300)
                {
                    $event->setCancelled(true);
                }
            }
        }
    }

    public function onBlockPlace(BlockPlaceEvent $event)
    {
        $player = $event->getPlayer();
        $level = $player->getLevel()
            ->getFolderName();
        if (in_array($level, $this->arenas))
        {
            $config = new Config($this->getDataFolder() . "/config.yml", Config::YAML);
            if ($config->get($level . "PlayTime") != null)
            {
                if ($config->get($level . "PlayTime") >= 300)
                {
                    $event->setCancelled(true);
                }
            }
        }
    }

    public function onDamage(EntityDamageEvent $event)
    {
        if ($event->getEntity() instanceof Player)
        {
            $victim = $event->getEntity();
            $level = $victim->getLevel()
                ->getFolderName();
            if (!in_array($level, $this->arenas)) return;
            $config = new Config($this->getDataFolder() . "/config.yml", Config::YAML);
            $time = $config->get($level . "PlayTime");
            $startTime = $config->get($level . "StartTime");
            if ($time !== null)
            {
                if ($startTime > 0)
                {
                    $event->setCancelled(true);
                    return;
                }
                if ($time >= 180)
                {
                    if ($event instanceof EntityDamageByEntityEvent)
                    {
                        $damager = $event->getDamager();
                        if ($damager instanceof Player)
                        {
                            $event->setCancelled(true);
                            $damager->sendMessage($this->prefix . "§cPvP is disabled until Deathmatch!");
                        }
                    }
                }
                else
                {
                    if ($event instanceof EntityDamageByEntityEvent)
                    {
                        $damager = $event->getDamager();
                        if ($damager instanceof Player)
                        {
                            $this->applyKnockback($victim, $damager, 0.3);
                        }
                    }
                }
            }
        }
    }

    public function onCommand(CommandSender $player, Command $cmd, $label, array $args)
    {
        switch ($cmd->getName())
        {
            case "hg":
                if (!empty($args[0]) && $args[0] == "leave")
                {
                    if ($player instanceof Player)
                    {
                        $this->leaveArena($player);
                    }
                    return true;
                }

                if (!empty($args[0]) && $args[0] == "join")
                {
                    $bestArena = null;
                    $maxPlayers = - 1;
                    $config = new Config($this->getDataFolder() . "/config.yml", Config::YAML);

                    foreach ($this->arenas as $arenaName)
                    {
                        $level = $this->getServer()
                            ->getLevelByName($arenaName);
                        if (!$level) continue;

                        $playTime = $config->get($arenaName . "PlayTime");
                        if ($playTime != 300) continue;

                        $playersCount = count($level->getPlayers());
                        if ($playersCount >= 24) continue;

                        if ($playersCount > $maxPlayers)
                        {
                            $maxPlayers = $playersCount;
                            $bestArena = $arenaName;
                        }
                    }

                    if ($bestArena !== null)
                    {
                        $level = $this->getServer()
                            ->getLevelByName($bestArena);
                        $aop = count($level->getPlayers());
                        $thespawn = $config->get($bestArena . "Spawn" . ($aop + 1));
                        if ($thespawn)
                        {
                            $spawn = new Position($thespawn[0] + 0.5, $thespawn[1], $thespawn[2] + 0.5, $level);
                            $level->loadChunk($spawn->getFloorX() , $spawn->getFloorZ());
                            $player->getInventory()
                                ->clearAll();
                            $player->getInventory()
                                ->setHelmet(Item::get(0, 0, 0));
                            $player->getInventory()
                                ->setChestplate(Item::get(0, 0, 0));
                            $player->getInventory()
                                ->setLeggings(Item::get(0, 0, 0));
                            $player->getInventory()
                                ->setBoots(Item::get(0, 0, 0));
                            $player->setGamemode(0);
                            $player->teleport($spawn, 0, 0);
                            $player->setHealth(20);
                            $player->setFood(20);
                            $player->getInventory()
                                ->setItem(8, $this->getLeaveItem());
                            foreach ($level->getPlayers() as $pl)
                            {
                                $pl->sendMessage($this->prefix . "§e" . $player->getName() . " §fhas joined the game.");
                            }
                            $this->giveRankKit($player);
                        }
                        else
                        {
                            $player->sendMessage($this->prefix . "Error joining arena (Spawn not set).");
                        }
                    }
                    else
                    {
                        $player->sendMessage($this->prefix . "No arenas available.");
                    }
                    return true;
                }

                if ($player->isOp())
                {
                    if (!empty($args[0]))
                    {
                        if ($args[0] == "criar")
                        {
                            if (!empty($args[1]))
                            {
                                if (file_exists($this->getServer()
                                    ->getDataPath() . "/worlds/" . $args[1]))
                                {
                                    $this->getServer()
                                        ->loadLevel($args[1]);
                                    $this->getServer()
                                        ->getLevelByName($args[1])->loadChunk($this->getServer()
                                        ->getLevelByName($args[1])->getSafeSpawn()
                                        ->getFloorX() , $this->getServer()
                                        ->getLevelByName($args[1])->getSafeSpawn()
                                        ->getFloorZ());
                                    array_push($this->arenas, $args[1]);
                                    $this->currentLevel = $args[1];
                                    $this->mode = 1;
                                    $player->sendMessage($this->prefix . "Touch blocks to register spawns!");
                                    $player->setGamemode(1);
                                    $player->teleport($this->getServer()
                                        ->getLevelByName($args[1])->getSafeSpawn() , 0, 0);
                                    $name = $args[1];
                                    $this->zipper($player, $name);
                                }
                                else
                                {
                                    $player->sendMessage($this->prefix . "ERROR world not found.");
                                }
                            }
                            else
                            {
                                $player->sendMessage($this->prefix . "ERROR parameters missing.");
                            }
                        }
                        else if ($args[0] == "sair" || $args[0] == "leave")
                        {
                            if ($player instanceof Player)
                            {
                                $this->leaveArena($player);
                            }
                        }
                        else
                        {
                            $player->sendMessage($this->prefix . "Invalid command.");
                        }
                    }
                    else
                    {
                        $player->sendMessage($this->prefix . "Missing parameters.");
                    }
                }
                else
                {
                    if (!empty($args[0]))
                    {
                        if ($args[0] == "sair" || $args[0] == "leave")
                        {
                            if ($player instanceof Player)
                            {
                                $this->leaveArena($player);
                            }
                        }
                        if ($args[0] == "info")
                        {
                            $player->sendMessage("§aPlugin Modified by: §bsevenzero");
                        }
                    }
                }
                return true;
            case "hginiciar":
                if ($player->isOp())
                {
                    $player->sendMessage("§aStarting in 10 seconds...");
                    $config = new Config($this->getDataFolder() . "/config.yml", Config::YAML);
                    $config->set("arenas", $this->arenas);
                    foreach ($this->arenas as $arena)
                    {
                        $config->set($arena . "PlayTime", 1380);
                        $config->set($arena . "StartTime", 10);
                    }
                    $config->save();
                }
                else
                {
                    $player->sendMessage("§cYou are not OP");
                }
                return true;
            case "batalhafinal":
                if ($player->isOp())
                {
                    $player->sendMessage("§aDeathmatch in 10 seconds...");
                    $config = new Config($this->getDataFolder() . "/config.yml", Config::YAML);
                    $config->set("arenas", $this->arenas);
                    foreach ($this->arenas as $arena)
                    {
                        $config->set($arena . "PlayTime", 190);
                        $config->set($arena . "StartTime", 0);
                    }
                    $config->save();
                }
                else
                {
                    $player->sendMessage("§cYou are not OP");
                }
                break;
            }
        }

        public function onInteract(PlayerInteractEvent $event)
        {
            $player = $event->getPlayer();
            $item = $event->getItem();
            $block = $event->getBlock();

            if ($item->getId() == 355 && $item->getCustomName() == "§c§lLeave Game")
            {
                $event->setCancelled(true);
                $this->leaveArena($player);
                return;
            }

            $tile = $player->getLevel()
                ->getTile($block);
            if ($tile instanceof Sign)
            {
                if ($this->mode == 26)
                {
                    $tile->setText(TextFormat::WHITE . "[§aJoin§f]", TextFormat::YELLOW . "0/24", $this->currentLevel, $this->prefix);
                    $this->refreshArenas();
                    $this->currentLevel = "";
                    $this->mode = 0;
                    $player->sendMessage($this->prefix . "Arena registered!");
                }
                else
                {
                    $text = $tile->getText();
                    if ($text[3] == $this->prefix)
                    {
                        if ($text[0] == TextFormat::WHITE . "[§aJoin§f]")
                        {
                            $config = new Config($this->getDataFolder() . "/config.yml", Config::YAML);
                            $level = $this->getServer()
                                ->getLevelByName($text[2]);
                            $aop = count($level->getPlayers());
                            $thespawn = $config->get($text[2] . "Spawn" . ($aop + 1));
                            $spawn = new Position($thespawn[0] + 0.5, $thespawn[1], $thespawn[2] + 0.5, $level);
                            $level->loadChunk($spawn->getFloorX() , $spawn->getFloorZ());
                            $player->getInventory()
                                ->clearAll();
                            $player->getInventory()
                                ->setHelmet(Item::get(0, 0, 0));
                            $player->getInventory()
                                ->setChestplate(Item::get(0, 0, 0));
                            $player->getInventory()
                                ->setLeggings(Item::get(0, 0, 0));
                            $player->getInventory()
                                ->setBoots(Item::get(0, 0, 0));
                            $player->setGamemode(0);
                            $player->teleport($spawn, 0, 0);
                            $amount = 20;
                            $player->setHealth($amount);
                            $player->setFood(20);
                            $player->getInventory()
                                ->setItem(8, $this->getLeaveItem());
                            foreach ($level->getPlayers() as $pl)
                            {
                                $pl->sendMessage($this->prefix . "§e" . $player->getName() . " §fhas joined the game.");
                            }
                            $this->giveRankKit($player);
                        }
                        else
                        {
                            $player->sendMessage($this->prefix . "§cGame already started.");
                        }
                    }
                }
            }
            else if ($this->mode >= 1 && $this->mode <= 24)
            {
                $config = new Config($this->getDataFolder() . "/config.yml", Config::YAML);
                $config->set($this->currentLevel . "Spawn" . $this->mode, array(
                    $block->getX() ,
                    $block->getY() + 1,
                    $block->getZ()
                ));
                $player->sendMessage($this->prefix . "Spawn " . $this->mode . " registered!");
                $this->mode++;
                if ($this->mode == 25)
                {
                    $player->sendMessage($this->prefix . "Now touch a block to register Deathmatch spawn.");
                }
                $config->save();
            }
            else if ($this->mode == 25)
            {
                $config = new Config($this->getDataFolder() . "/config.yml", Config::YAML);
                $level = $this->getServer()
                    ->getLevelByName($this->currentLevel);
                $level->setSpawn = (new Vector3($block->getX() , $block->getY() + 2, $block->getZ()));
                $config->set("arenas", $this->arenas);
                $player->sendMessage($this->prefix . "Touch a sign to register the Arena!");
                $spawn = $this->getServer()
                    ->getDefaultLevel()
                    ->getSafeSpawn();
                $this->getServer()
                    ->getDefaultLevel()
                    ->loadChunk($spawn->getFloorX() , $spawn->getFloorZ());
                $player->teleport($spawn, 0, 0);
                $config->save();
                $this->mode = 26;
            }
        }

        public function refreshArenas()
        {
            $config = new Config($this->getDataFolder() . "/config.yml", Config::YAML);
            $config->set("arenas", $this->arenas);
            foreach ($this->arenas as $arena)
            {
                $config->set($arena . "PlayTime", 300);
                $config->set($arena . "StartTime", 30);
            }
            $config->save();
        }

        public function zipper($player, $name)
        {
            $path = realpath($player->getServer()
                ->getDataPath() . 'worlds/' . $name);
            $zip = new \ZipArchive;
            @mkdir($this->getDataFolder() . 'arenas/', 0755);
            $zip->open($this->getDataFolder() . 'arenas/' . $name . '.zip', $zip::CREATE | $zip::OVERWRITE);
            $files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path) , \RecursiveIteratorIterator::LEAVES_ONLY);
            foreach ($files as $datos)
            {
                if (!$datos->isDir())
                {
                    $relativePath = $name . '/' . substr($datos, strlen($path) + 1);
                    $zip->addFile($datos, $relativePath);
                }
            }
            $zip->close();
            $player->getServer()
                ->loadLevel($name);
            unset($zip, $path, $files);
        }
    }

    class ScoreboardTask extends PluginTask
    {
        public $prefix = "§8(§2H§fG§8)§f ";

        public function __construct($plugin)
        {
            $this->plugin = $plugin;
            parent::__construct($plugin);
        }

        public function onRun($tick)
        {
            $config = new Config($this
                ->plugin
                ->getDataFolder() . "/config.yml", Config::YAML);
            $arenas = $config->get("arenas");
            if (!empty($arenas))
            {
                foreach ($arenas as $arena)
                {
                    $levelArena = $this
                        ->plugin
                        ->getServer()
                        ->getLevelByName($arena);
                    if ($levelArena instanceof Level)
                    {
                        $allplayers = $this
                            ->plugin
                            ->getServer()
                            ->getOnlinePlayers();
                        $playersArena = array();
                        foreach ($allplayers as $play)
                        {
                            if ($play->getLevel()
                                ->getFolderName() == $arena)
                            {
                                array_push($playersArena, $play);
                            }
                        }

                        $time = $config->get($arena . "PlayTime");
                        $timeToStart = $config->get($arena . "StartTime");
                        $playerCount = count($playersArena);

                        foreach ($playersArena as $pl)
                        {
                            $status = "§aWaiting";
                            $timeDisplay = "";

                            if ($timeToStart > 0 && $playerCount >= 2)
                            {
                                $status = "§eStarting";
                                $timeDisplay = "\n§7Time: §f" . $timeToStart . "s";
                            }
                            else if ($time < 300 && $time > 0)
                            {
                                $status = "§cIn Game";
                                $mins = floor($time / 60);
                                $secs = $time % 60;
                                $timeDisplay = "\n§7Time: §f" . $mins . ":" . str_pad($secs, 2, "0", STR_PAD_LEFT);
                            }
                            $uppers = str_repeat("\n", 5);
                            $spaces = str_repeat(" ", 60);
                            $scoreboard = $spaces . "§l§2HUNGER§fGAMES§r\n";
                            $scoreboard .= $spaces . "§7Map: §f" . $arena . "\n";
                            $scoreboard .= $spaces . "§7Players: §f" . $playerCount . "/24\n";
                            $scoreboard .= $spaces . "§7Status: " . $status;
                            if ($timeDisplay != "")
                            {
                                $scoreboard .= "\n" . $spaces . "§7Time: §f" . substr($timeDisplay, 9);
                            }

                            $pl->sendTip($scoreboard);
                        }
                    }
                }
            }
        }
    }

    class RefreshSigns extends PluginTask
    {
        public $prefix = "§8(§2H§fG§8)§f ";
        public function __construct($plugin)
        {
            $this->plugin = $plugin;
            parent::__construct($plugin);
        }
        public function onRun($tick)
        {
            $allplayers = $this
                ->plugin
                ->getServer()
                ->getOnlinePlayers();
            $level = $this
                ->plugin
                ->getServer()
                ->getDefaultLevel();
            $tiles = $level->getTiles();
            foreach ($tiles as $t)
            {
                if ($t instanceof Sign)
                {
                    $text = $t->getText();
                    if ($text[3] == $this->prefix)
                    {
                        $aop = 0;
                        foreach ($allplayers as $player)
                        {
                            if ($player->getLevel()
                                ->getFolderName() == $text[2])
                            {
                                $aop = $aop + 1;
                            }
                        }
                        $ingame = TextFormat::WHITE . "[§aJoin§f]";
                        $config = new Config($this
                            ->plugin
                            ->getDataFolder() . "/config.yml", Config::YAML);
                        if ($config->get($text[2] . "PlayTime") != 300)
                        {
                            $ingame = TextFormat::GRAY . "[§4INGAME§7]";
                        }
                        else if ($aop >= 24)
                        {
                            $ingame = TextFormat::GRAY . "[§4FULL§7]";
                        }
                        $t->setText($ingame, TextFormat::YELLOW . $aop . "/24", $text[2], $this->prefix);
                    }
                }
            }
        }
    }

    class GameSender extends PluginTask
    {
        public $prefix = "§8(§2H§fG§8)§f ";
        public $nextRefill = [];

        public function __construct($plugin) {
            $this->plugin = $plugin;
            parent::__construct($plugin);
        }

        public function getResetmap() {
            return new ResetMap($this);
        }
        
        public function getItems() {
             return [
                [306, 0, 1], [307, 0, 1], [308, 0, 1], [309, 0, 1],
                [302, 0, 1], [303, 0, 1], [304, 0, 1], [305, 0, 1],
                [314, 0, 1], [315, 0, 1], [316, 0, 1], [317, 0, 1],
                [310, 0, 1], [311, 0, 1], [312, 0, 1], [313, 0, 1],
                [272, 0, 1],
                [267, 0, 1],
                [276, 0, 1],
                [261, 0, 1],
                [364, 0, 3], [364, 0, 5],
                [322, 0, 1],
                [322, 0, 2],
                [262, 0, 5], [262, 0, 10],
                [373, 14, 1],
                [373, 21, 1],
                [373, 16, 1],
                [4, 0, 16],
                [5, 0, 16],
                [259, 0, 1],
                [46, 0, 2],
                [30, 0, 1],
            ];
        }

        public function onRun($tick)
        {
            $config = new Config($this->plugin->getDataFolder() . "/config.yml", Config::YAML);

            $arenas = $config->get("arenas");
            if (!empty($arenas))
            {
                foreach ($arenas as $arena)
                {
                    $time = $config->get($arena . "PlayTime");
                    $timeToStart = $config->get($arena . "StartTime");
                    $levelArena = $this
                        ->plugin
                        ->getServer()
                        ->getLevelByName($arena);
                    if ($levelArena instanceof Level)
                    {
                        $allplayers = $this
                            ->plugin
                            ->getServer()
                            ->getOnlinePlayers();
                        $playersArena = array();

                        foreach ($allplayers as $play) {
                            if ($play->getLevel()->getFolderName() == $arena) {
                                array_push($playersArena, $play);
                            }
                        }

                        if (count($playersArena) == 0)
                        {
                            $config->set($arena . "PlayTime", 300);
                            $config->set($arena . "StartTime", 30);
                            unset($this->nextRefill[$arena]);
                        }
                        else
                        {
                            if (count($playersArena) >= 2)
                            {
                                if ($timeToStart > 0)
                                {
                                    $timeToStart--;

                                    if ($timeToStart <= 0)
                                    {
                                        $this->refillChests($levelArena);
                                        $this->nextRefill[$arena] = 300 - rand(45, 60);

                                    }
                                    $config->set($arena . "StartTime", $timeToStart);

                                }
                                else
                                {
                                    if (isset($this->nextRefill[$arena]) && $time <= $this->nextRefill[$arena]) {
                                        $this->refillChests($levelArena);
                                        foreach ($playersArena as $pl) {
                                            $pl->sendMessage($this->prefix . "§aChests have been refilled!");
                                        }
                                        $this->nextRefill[$arena] = $time - rand(45, 60);
                                    }

                                    $aop = count($levelArena->getPlayers());

                                    if ($aop == 1)
                                    {
                                        foreach ($playersArena as $pl)
                                        {

                                            $this->plugin->getServer()->broadcastMessage($this->prefix . $pl->getName() . " §bwon the game.");
                                            $this
                                                ->plugin
                                                ->MOD_top_module
                                                ->onWin($pl);
                                            $this
                                                ->plugin
                                                ->MOD_top_module
                                                ->reloadData();

                                            $pl->getInventory()
                                                ->clearAll();
                                            $pl->removeAllEffects();
                                            $pl->getInventory()
                                                ->setHelmet(Item::get(0, 0, 0));
                                            $pl->getInventory()
                                                ->setChestplate(Item::get(0, 0, 0));
                                            $pl->getInventory()
                                                ->setLeggings(Item::get(0, 0, 0));
                                            $pl->getInventory()
                                                ->setBoots(Item::get(0, 0, 0));
                                            $this->getResetmap()
                                                ->reload($levelArena);
                                            $spawn = $this
                                                ->plugin
                                                ->getServer()
                                                ->getDefaultLevel()
                                                ->getSafeSpawn();
                                            $this
                                                ->plugin
                                                ->getServer()
                                                ->getDefaultLevel()
                                                ->loadChunk($spawn->getX() , $spawn->getZ());
                                            $pl->teleport($spawn, 0, 0);
                                            
                                        }

                                        $config->set($arena . "PlayTime", 300);
                                        $config->set($arena . "StartTime", 30);
                                        return;
                                    }
                                    if (($aop >= 2))
                                    {
                                        foreach ($playersArena as $pl)
                                        {
                                            $level = $pl->getLevel()
                                                ->getName();
                                            $x = floor($pl->getX());
                                            $y = floor($pl->getY());
                                            $z = floor($pl->getZ());
                                        }
                                    }
                                    $time--;
                                    if ($time == 299)
                                    {
                                        foreach ($playersArena as $pl)
                                        {
                                            $levelArena->addSound(new AnvilUseSound($pl));
                                            $pl->getInventory()
                                                ->clearAll();
                                            $pl->sendMessage("§6The match has started, good luck!");
                                        }
                                    }
                                    if ($time >= 180)
                                    {
                                        $time2 = $time - 180;
                                        $minutes = $time2 / 60;
                                        if (is_int($minutes) && $minutes > 0)
                                        {
                                            foreach ($playersArena as $pl)
                                            {
                                                $pl->sendMessage($this->prefix . "§c" . $minutes . " §fMinutes to Deathmatch");
                                            }
                                        }
                                        else if ($time2 == 30 || $time2 == 15 || $time2 == 10 || $time2 == 5 || $time2 == 4 || $time2 == 3 || $time2 == 2 || $time2 == 1)
                                        {
                                            foreach ($playersArena as $pl)
                                            {
                                                $pl->sendMessage($this->prefix . "§c" . $time2 . " §fSeconds to Deathmatch");
                                            }
                                        }
                                        if ($time2 <= 0)
                                        {
                                            $spawn = $levelArena->getSafeSpawn();
                                            $levelArena->loadChunk($spawn->getX() , $spawn->getZ());
                                            foreach ($playersArena as $pl)
                                            {
                                                $pl->teleport($spawn, 0, 0);
                                            }
                                        }
                                    }
                                    else
                                    {
                                        $minutes = $time / 60;
                                        if (is_int($minutes) && $minutes > 0)
                                        {
                                            foreach ($playersArena as $pl)
                                            {
                                                $pl->sendMessage($this->prefix . "§c" . $minutes . " §fMinutes remaining");
                                            }
                                        }
                                        else if ($time == 30 || $time == 15 || $time == 10 || $time == 5 || $time == 4 || $time == 3 || $time == 2 || $time == 1)
                                        {
                                            foreach ($playersArena as $pl)
                                            {
                                                $pl->sendMessage($this->prefix . "§c" . $time . " §fSeconds remaining");
                                            }
                                        }
                                        if ($time <= 0)
                                        {
                                            $spawn = $this
                                                ->plugin
                                                ->getServer()
                                                ->getDefaultLevel()
                                                ->getSafeSpawn();
                                            $this
                                                ->plugin
                                                ->getServer()
                                                ->getDefaultLevel()
                                                ->loadChunk($spawn->getX() , $spawn->getZ());
                                            foreach ($playersArena as $pl)
                                            {
                                                $pl->teleport($spawn, 0, 0);
                                                $pl->sendMessage($this->prefix . "§fNo one won this time");
                                                $pl->getInventory()
                                                    ->clearAll();
                                                $pl->removeAllEffects();
                                                $pl->getInventory()
                                                    ->setHelmet(Item::get(0, 0, 0));
                                                $pl->getInventory()
                                                    ->setChestplate(Item::get(0, 0, 0));
                                                $pl->getInventory()
                                                    ->setLeggings(Item::get(0, 0, 0));
                                                $pl->getInventory()
                                                    ->setBoots(Item::get(0, 0, 0));
                                                $this->getResetmap()
                                                    ->reload($levelArena);
                                            }
                                            $time = 300;
                                        }
                                    }
                                    $config->set($arena . "PlayTime", $time);
                                }
                            }
                            else
                            {
                                if ($timeToStart <= 0)
                                {
                                    foreach ($playersArena as $pl)
                                    {
                                        foreach ($this
                                            ->plugin
                                            ->getServer()
                                            ->getOnlinePlayers() as $plpl)
                                        {
                                            $plpl->sendMessage($this->prefix . $pl->getName() . " §bwon the game.");
                                            $this
                                                ->plugin
                                                ->MOD_top_module
                                                ->onWin($pl);
                                            $this
                                                ->plugin
                                                ->MOD_top_module
                                                ->reloadData();
                                    }
                                        $spawn = $this
                                            ->plugin
                                            ->getServer()
                                            ->getDefaultLevel()
                                            ->getSafeSpawn();
                                        $this
                                            ->plugin
                                            ->getServer()
                                            ->getDefaultLevel()
                                            ->loadChunk($spawn->getX() , $spawn->getZ());
                                        $pl->getInventory()
                                            ->clearAll();
                                        $pl->removeAllEffects();
                                        $pl->getInventory()
                                            ->setHelmet(Item::get(0, 0, 0));
                                        $pl->getInventory()
                                            ->setChestplate(Item::get(0, 0, 0));
                                        $pl->getInventory()
                                            ->setLeggings(Item::get(0, 0, 0));
                                        $pl->getInventory()
                                            ->setBoots(Item::get(0, 0, 0));
                                        $pl->teleport($spawn);
                                        $this->getResetmap()
                                            ->reload($levelArena);
                                    }
                                    $config->set($arena . "PlayTime", 300);
                                    $config->set($arena . "StartTime", 30);
                                    return;
                                }
                                else
                                {
                                    $config->set($arena . "PlayTime", 300);
                                    $config->set($arena . "StartTime", 30);
                                }
                            }
                        }
                    }

                }

            }
            $config->save();
        }
        public function refillChests(Level $level)
        {
            $tiles = $level->getTiles();
            $items = $this->getItems();
            foreach ($tiles as $t)
            {
                if ($t instanceof Chest)
                {
                    $chest = $t;
                    $inv = $chest->getInventory();
                    
                    // Refill all empty chests (or just all chests?)
                    // "refill all empty chests" - user said this.
                    // But then "refill chests every 1 min".
                    // Assuming we clear and refill if it's considered for refill.
                    
                    // Logic: Just clear and fill random slots.
                    // If we want to strictly follow "refill empty chests", check if empty.
                    // But players might leave garbage.
                    // I will clear and refill.
                    
                    $inv->clearAll();
                    
                    if ($inv instanceof ChestInventory)
                    {
                        $amount = rand(3, 6);
                        for ($i = 0; $i < $amount; $i++)
                        {
                            $slot = rand(0, 26);
                            $k = array_rand($items);
                            $v = $items[$k];
                            $inv->setItem($slot, Item::get($v[0], $v[1], $v[2]));
                        }
                    }
                }
            }
        }
    }
    
