<?php

namespace bedwars\util;

use pocketmine\level\format\FullChunk;
use pocketmine\level\sound\AnvilUseSound;

use pocketmine\item\Item;
use pocketmine\math\Vector3;

use pocketmine\level\Level;

use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\tag\DoubleTag;
use pocketmine\nbt\tag\ShortTag;
use pocketmine\nbt\tag\FloatTag;
use pocketmine\nbt\tag\ByteTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\math\AxisAlignedBB;

use pocketmine\Player;

use bedwars\entity\GeneretorText;
use bedwars\entity\IconBlock;

class GeneretorFill {
    
    const TYPE_FORMAT = array("diamond" => "§r§bDiamond", "esmerald" => "§r§aEmerald");
    
    const LOADING_FORMAT = [
        "-",
        "\\",
        "|",
        "/",
        "-",
        "\\",
        "|",
        "/"
        
    ];
    
    /** @var IconBlock */
    private $iconBlock;
    
    /** @var int */
    private $timeUpdate = 0;
    private $loading = 0;
    private $tier = 0;

    /** @var string */
    private $type;

    /** @var GeneretorText */
    private $text;

    /** @var Level */
    private $level;

    /** @var int */
    private $x;
    private $y;
    private $z;
    
    /**
     * @return string
     */
    public function getType() : string {
        return $this->type;
    }
    
    /**
     * @return int
     */
    public function getTier() : int {
        return $this->tier;
    }
    
    /**
     * @param int
     */
    public function setTier(int $tier) {
        $this->tier = $tier;
    }
    
    /**
     * @return int
     */
    public function getTime() : int {
        return $this->time;
    }
    
    /**
     * @param int $time
     */
    public function setTime(int $time) {
        $this->time = $time;
    }
    
    /** 
     * @return int
     */
    public function getTierCount(int $tier) {
        $tiers = array(1 => 0, 2 => 8, 3 => 12);
        return $tiers[$tier];
    }
    
    /**
     * @return int
     */
    public function getMaxTime() : int {
        $values = array("diamond" => 25, "esmerald" => 40);
        $time = $values[$this->getType()];
        $time -= $this->getTierCount($this->getTier());
        return $time;
    }
    
    /**
     * @return level
     */
    public function getLevel() : Level {
        return $this->level;
    }
    
    /**
     * @param Level $level
     */
    public function setLevel(Level $level) {
        $this->level = $level;
    }

    /**
    * @return GeneretorText
    */
    public function getText() : GeneretorText {
        return $this->text;
    }
    
    /**
     * @param GeneretorText $text
     */
    public function setText(GeneretorText $text) {
        $this->text = $text;
    }

    /**
    * @param int    $x
    * @param int    $y
    * @param int    $z
    * @param Level  $level
    * @param int    $tier
    * @param string $type
    * @param int    $time
    */
    public function __construct($x, $y, $z, Level $level, int $tier, string $type, int $time) {
        $this->x = $x;
        $this->y = $y;
        $this->z = $z;
        $this->level = $level;

        $this->tier = $tier;
        $this->type = $type;
        $this->time = $time;

        $this->createText();
        $this->addIconBlock();
    }
	
    /**
     * @return array
     */
    public function getFormat() : array {
        $max_barrie = 15;
        $start = ($max_barrie / $this->getMaxTime()) * $this->getTime();
        
        if ($start > $max_barrie) {
        	$start = $max_barrie;
        }
        
        $loading = self::LOADING_FORMAT[$this->loading++];
        
        if (($this->loading + 1) >= count(self::LOADING_FORMAT)) {
            $this->loading = 0;
        }

        $left = ($max_barrie - $start);
        $barries = "§a" . str_repeat("#", $left) . "§7" . str_repeat("#", $start);
        $lines = [];
        $lines[] = '§aLevel§c ' . str_repeat("I", $this->getTier());
        $lines[] = self::TYPE_FORMAT[$this->getType()];
        $lines[] = "";
        $lines[] = "§l§f{$loading}§r §l{$barries}";
        return $lines;
    }
    
    /**
     * @return int
     */
    public function getTypeId($value = false) : int {
        $blocks = array("diamond" => 57, "esmerald" => 133);
        $itens = array("diamond" => 264, "esmerald" => 388);
        
        if ($value) {
        	return $itens[$this->getType()];
        } else {
        	return $blocks[$this->getType()];
        }
    }

  	/**
  	* @param bool $item
  	*/ 	 
    public function addIconBlock(bool $item = false) {
        if (!($this->getText() instanceof GeneretorText)) {
            return false;
        }
        $namedtag = $this->getText()->namedtag;
        $namedtag->ItemMETA = new IntTag("ItemMETA", $this->getTypeId());
        $namedtag->Pos = new ListTag("Pos", array(
            new DoubleTag(0, $this->x),
            new DoubleTag(0, $this->y + 1.3),
            new DoubleTag(0, $this->z)
        ));

        $chunk = $this->level->getChunk($this->x >> 4, $this->z >> 4, true);

        $iconBlock = new IconBlock($chunk, $namedtag);
      	$iconBlock->spawnToAll();

      	$this->iconBlock = $iconBlock;
    }
    
    public function stop() {
    	if ($this->iconBlock instanceof IconBlock) {
    		$this->iconBlock->close();
    		$this->iconBlock = null;
    	}

        if ($this->text instanceof GeneretorText) {
            $this->text->close();
        }
    }

    public function onUpdate() {
        if ($this->getTime() <= 0) {
            $this->setTime($this->getMaxTime());
            $this->level->dropItem(new Vector3($this->x, $this->y - 0.5, $this->z), Item::get($this->getTypeId(true)), new Vector3(0, 0 ,0));
        } else {
            $this->setTime($this->getTime() - 1);
        }

        $distance = 45;
        $has = false;

        foreach($this->level->getNearbyEntities(new AxisAlignedBB($this->x - $distance, $this->y - $distance, $this->z - $distance, $this->x + $distance, $this->y + $distance, $this->z + $distance)) as $entity) {
            if ($entity instanceof Player) {
                $has = true;
                break;
            }
        }

        $text = $this->getText();
        $canCreate = false;

        if ($has) {
            if ($text instanceof GeneretorText) {
                if ($text->closed === false) {
                    $text->addLines($this->getFormat());
                    //
                } else {
                    $canCreate = true;
                }
            } else {
                $canCreate = true;
            }
        } else {
            if ($text instanceof GeneretorText) {
                if ($text->closed === false) {
                    $text->close();
                }
            }
        }

        if ($canCreate) {
            if ($text instanceof GeneretorText) {
                $text->close();
            }

            $this->createText();
        }
    }

    public function createText() {
        $nbt = new CompoundTag("", []);
        $nbt->Pos = new ListTag("Pos", [
            new DoubleTag(0, $this->x),
            new DoubleTag(1, $this->y),
            new DoubleTag(2, $this->z)
        ]);
        $nbt->Rotation = new ListTag("Rotation", [
            new FloatTag(0, 0),
            new FloatTag(1, 0)
        ]);
        $nbt->Motion = new ListTag("Motion", [
            new DoubleTag(0, 0),
            new DoubleTag(1, 0),
            new DoubleTag(2, 0)
        ]);

        $nbt->Health = new ShortTag("Health", 1);
        $nbt->Invisible = new IntTag("Invisible", 1);
        $nbt->Parent = new CompoundTag("Parent", []);
        $nbt->Viewers = new CompoundTag("Viewers", []);

        $chunk = $this->level->getChunk($this->x >> 4, $this->z >> 4, true);

        $text = new GeneretorText($chunk, $nbt);
        $text->spawnToAll();

        $this->text = $text;
    }
}
?>