

#pragma once

#include "ItemHandler.h"
#include "../World.h"
#include "../Blocks/BlockHandler.h"
#include "../BlockEntities/BannerEntity.h"
#include "../Blocks/ChunkInterface.h"





class cItemBannerHandler final:
	public cItemHandler
{
	using Super = cItemHandler;

public:

	using Super::Super;

private:

	virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override
	{
		// Cannot place a banner at "no face" and from the bottom:
		if ((a_ClickedBlockFace == BLOCK_FACE_NONE) || (a_ClickedBlockFace == BLOCK_FACE_BOTTOM))
		{
			return false;
		}

		if (!TryPlaceBanner(a_Player, a_PlacePosition, a_ClickedBlockFace))
		{
			return false;
		}

		a_Player.GetWorld()->DoWithBlockEntityAt(a_PlacePosition, [&a_HeldItem](cBlockEntity & a_BlockEntity)
		{
			ASSERT((a_BlockEntity.GetBlockType() == E_BLOCK_STANDING_BANNER) || (a_BlockEntity.GetBlockType() == E_BLOCK_WALL_BANNER));

			cBannerEntity & BannerEntity = static_cast<cBannerEntity &>(a_BlockEntity);
			BannerEntity.SetBaseColor(static_cast<NIBBLETYPE>(a_HeldItem.m_ItemDamage));
			BannerEntity.SetCustomName(a_HeldItem.m_CustomName);
			return false;
		});

		return true;
	}





	virtual bool IsPlaceable(void) const override
	{
		return true;
	}




	static bool TryPlaceBanner(cPlayer & a_Player, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace)
	{
		const auto Rotation = a_Player.GetYaw();

		// Placing on the floor:
		if (a_ClickedBlockFace == BLOCK_FACE_TOP)
		{
			NIBBLETYPE Meta;

			if ((Rotation >= -11.25f) && (Rotation < 11.25f))
			{
				// South
				Meta = 0x08;
			}
			else if ((Rotation >= 11.25f) && (Rotation < 33.75f))
			{
				// SouthSouthWest
				Meta = 0x09;
			}
			else if ((Rotation >= 23.75f) && (Rotation < 56.25f))
			{
				// SouthWest
				Meta = 0x0a;
			}
			else if ((Rotation >= 56.25f) && (Rotation < 78.75f))
			{
				// WestSouthWest
				Meta = 0x0b;
			}
			else if ((Rotation >= 78.75f) && (Rotation < 101.25f))
			{
				// West
				Meta = 0x0c;
			}
			else if ((Rotation >= 101.25f) && (Rotation < 123.75f))
			{
				// WestNorthWest
				Meta = 0x0d;
			}
			else if ((Rotation >= 123.75f) && (Rotation < 146.25f))
			{
				// NorthWest
				Meta = 0x0e;
			}
			else if ((Rotation >= 146.25f) && (Rotation < 168.75f))
			{
				// NorthNorthWest
				Meta = 0x0f;
			}
			else if ((Rotation >= -168.75f) && (Rotation < -146.25f))
			{
				// NorthNorthEast
				Meta = 0x01;
			}
			else if ((Rotation >= -146.25f) && (Rotation < -123.75f))
			{
				// NorthEast
				Meta = 0x02;
			}
			else if ((Rotation >= -123.75f) && (Rotation < -101.25f))
			{
				// EastNorthEast
				Meta = 0x03;
			}
			else if ((Rotation >= -101.25) && (Rotation < -78.75f))
			{
				// East
				Meta = 0x04;
			}
			else if ((Rotation >= -78.75) && (Rotation < -56.25f))
			{
				// EastSouthEast
				Meta = 0x05;
			}
			else if ((Rotation >= -56.25f) && (Rotation < -33.75f))
			{
				// SouthEast
				Meta = 0x06;
			}
			else if ((Rotation >= -33.75f) && (Rotation < -11.25f))
			{
				// SouthSouthEast
				Meta = 0x07;
			}
			else  // degrees jumping from 180 to -180
			{
				// North
				Meta = 0x00;
			}

			return a_Player.PlaceBlock(a_PlacePosition, E_BLOCK_STANDING_BANNER, Meta);
		}

		// We must be placing on the side of a block.

		NIBBLETYPE Meta;

		if (a_ClickedBlockFace == BLOCK_FACE_EAST)
		{
			Meta = 0x05;
		}
		else if (a_ClickedBlockFace == BLOCK_FACE_WEST)
		{
			Meta = 0x04;
		}
		else if (a_ClickedBlockFace == BLOCK_FACE_NORTH)
		{
			Meta = 0x02;
		}
		else  // degrees jumping from 180 to -180
		{
			Meta = 0x03;
		}

		return a_Player.PlaceBlock(a_PlacePosition, E_BLOCK_WALL_BANNER, Meta);
	}
};
