<?php

namespace bedwars\entity;

use pocketmine\network\protocol\AddPlayerPacket;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\event\entity\EntityDamageByEntityEvent;

use pocketmine\level\Position;

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\Player;

use pocketmine\entity\Entity;

use pocketmine\level\particle\LavaParticle;
use pocketmine\level\particle\LavaDripParticle;

use pocketmine\item\Item;

use bedwars\entity\api\EntityAPI;
use bedwars\entity\api\HumanAPI;
use bedwars\entity\api\Line;

class NPC extends HumanAPI {
    
    /**
     * @param Position $position
     * @param float    $yaw
     * @param float    $pitch
     * @paran float    $skinData
     * @param int      $skinId
     * @param bool     $invisible
     * @return bool
     */
	public static function createNBT(Position $position, $yaw , $pitch, $skinData, $skinId, bool $invisible = false) : CompoundTag {
		$nbt = new CompoundTag("", []);
		$nbt->Pos = new ListTag("Pos", [
			new DoubleTag(0, $position->x),
			new DoubleTag(1, $position->y),
			new DoubleTag(2, $position->z)
		]);
		$nbt->Rotation = new ListTag("Rotation", [
			new FloatTag(0, $yaw),
			new FloatTag(1, $pitch)
		]);
		$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", $invisible ? 1 : 0);
		
		$nbt->Skin = new CompoundTag("Skin", [
			"Data" => new StringTag("Data", $skinData),
			"Name" => new StringTag("Name", $skinId)
		]);
		$nbt->Parent = new CompoundTag("Parent", []);
		$nbt->Viewers = new CompoundTag("Viewers", []);
		return $nbt;
	}
	
	/**
	 * @return array
     */
	public static function init() : array {
		$initeds = [];
		$entities = [
			NPC::class, 
			HumanAPI::class, 
			EntityAPI::class, 
			Line::class, 
			Manager::class, 
			VillagerNPC::class, 
			Upgrade::class, 
			Shop::class, 
			GeneretorText::class,
			BedText::class, 
			IconBlock::class,
			FireBall::class,
			EnderPearl::class,
			BedWarsWins::class
		];
		
		foreach ($entities as $classDir) {
			$array = explode(DIRECTORY_SEPARATOR, $classDir);
			$className = end($array);
			$initeds[] = $className;
			
			Entity::registerEntity($classDir, true);
		}
		return $initeds;
	}

	/**
	 * @param float             $damage
	 * @param EntityDamageEvent $source
	 *
	 * @return bool
	 */
	public function attack($damage, EntityDamageEvent $source) {
		if ($source instanceof EntityDamageByEntityEvent and $source->getDamager() instanceof Player) {
			$damager = $source->getDamager();
			$item = $damager->getInventory()->getItemInHand();

			if ($item->getId() === Item::EMERALD) {
				if ($damager->hasPermission("bedwars.permission.remove.npc")) {
					$this->close();
				} else {
					//TODO:
				}
			}
		}
	}
	
	/**
	 * @param Player $player
	 */
	public function spawnTo(Player $player) {
		if ($player !== $this and !isset($this->hasSpawned[$player->getLoaderId()])) {
			$this->hasSpawned[$player->getLoaderId()] = $player;

			$invisible = $this->namedtag["Invisible"];

			if ($invisible <= 0) {
				$this->addPlayerList($player);
			}

			$pk = new AddPlayerPacket();
			$pk->uuid = $this->getUniqueId();
			$pk->username = $this->getName();
			$pk->eid = $this->getId();
			$pk->x = $this->x;
			$pk->y = $this->y;
			$pk->z = $this->z;
			$pk->speedX = $this->motionX;
			$pk->speedY = $this->motionY;
			$pk->speedZ = $this->motionZ;
			$pk->yaw = $this->yaw;
			$pk->pitch = $this->pitch;
			$pk->item = $this->getInventory()->getItemInHand();
			$pk->metadata = array (
					self::DATA_FLAGS => array (self::DATA_TYPE_BYTE, $invisible << self::DATA_FLAG_INVISIBLE),
					self::DATA_NO_AI => array (self::DATA_TYPE_BYTE, 1),
					self::DATA_LEAD_HOLDER => array (self::DATA_TYPE_LONG, -1),
					self::DATA_LEAD => array (self::DATA_TYPE_BYTE, 0)
	            );
			$player->dataPacket($pk);

			$this->sendLinkedData();

			$this->inventory->sendArmorContents($player);

			if ($invisible <= 0) {
				$this->removePlayerList($player);
			}
		}
	}
}