// Copyright (C) 2002-2012 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h

#ifndef __C_GUI_LIST_BOX_H_INCLUDED__
#define __C_GUI_LIST_BOX_H_INCLUDED__

#include "IGUIListBox.h"
#include "irrArray.h"

namespace irr
{
namespace gui
{

	class IGUIFont;
	class IGUIScrollBar;

	class CGUIListBox : public IGUIListBox
	{
	public:
		//! constructor
		CGUIListBox(IGUIEnvironment* environment, IGUIElement* parent,
			s32 id, core::rect<s32> rectangle, bool clip=true,
			bool drawBack=false, bool moveOverSelect=false);

		//! destructor
		virtual ~CGUIListBox();

		//! returns amount of list items
		u32 getItemCount() const override;

		//! returns string of a list item. the id may be a value from 0 to itemCount-1
		const wchar_t* getListItem(u32 id) const override;

		//! adds an list item, returns id of item
		u32 addItem(const wchar_t* text) override;

		//! clears the list
		void clear() override;

		//! returns id of selected item. returns -1 if no item is selected.
		s32 getSelected() const override;

		//! sets the selected item. Set this to -1 if no item should be selected
		void setSelected(s32 id) override;

		//! sets the selected item. Set this to -1 if no item should be selected
		void setSelected(const wchar_t *item) override;

		//! called if an event happened.
		bool OnEvent(const SEvent& event) override;

		//! draws the element and its children
		void draw() override;

		//! adds an list item with an icon
		//! \param text Text of list entry
		//! \param icon Sprite index of the Icon within the current sprite bank. Set it to -1 if you want no icon
		//! \return
		//! returns the id of the new created item
		u32 addItem(const wchar_t* text, s32 icon) override;

		//! Returns the icon of an item
		s32 getIcon(u32 id) const override;

		//! removes an item from the list
		void removeItem(u32 id) override;

		//! get the the id of the item at the given absolute coordinates
		s32 getItemAt(s32 xpos, s32 ypos) const override;

		//! Sets the sprite bank which should be used to draw list icons. This font is set to the sprite bank of
		//! the built-in-font by default. A sprite can be displayed in front of every list item.
		//! An icon is an index within the icon sprite bank. Several default icons are available in the
		//! skin through getIcon
		void setSpriteBank(IGUISpriteBank* bank) override;

		//! set whether the listbox should scroll to newly selected items
		void setAutoScrollEnabled(bool scroll) override;

		//! returns true if automatic scrolling is enabled, false if not.
		bool isAutoScrollEnabled() const override;

		//! Update the position and size of the listbox, and update the scrollbar
		void updateAbsolutePosition() override;

		//! set all item colors at given index to color
		void setItemOverrideColor(u32 index, video::SColor color) override;

		//! set all item colors of specified type at given index to color
		void setItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType, video::SColor color) override;

		//! clear all item colors at index
		void clearItemOverrideColor(u32 index) override;

		//! clear item color at index for given colortype
		void clearItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) override;

		//! has the item at index its color overwritten?
		bool hasItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const override;

		//! return the overwrite color at given item index.
		video::SColor getItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const override;

		//! return the default color which is used for the given colorType
		video::SColor getItemDefaultColor(EGUI_LISTBOX_COLOR colorType) const override;

		//! set the item at the given index
		void setItem(u32 index, const wchar_t* text, s32 icon) override;

		//! Insert the item at the given index
		//! Return the index on success or -1 on failure.
		s32 insertItem(u32 index, const wchar_t* text, s32 icon) override;

		//! Swap the items at the given indices
		void swapItems(u32 index1, u32 index2) override;

		//! set global itemHeight
		void setItemHeight( s32 height ) override;

		//! Sets whether to draw the background
		void setDrawBackground(bool draw) override;

		//! Access the vertical scrollbar
		IGUIScrollBar* getVerticalScrollBar() const override;

	private:

		struct ListItem
		{
			core::stringw Text;
			s32 Icon = -1;

			// A multicolor extension
			struct ListItemOverrideColor
			{
				bool Use = false;
				video::SColor Color;
			};
			ListItemOverrideColor OverrideColors[EGUI_LBC_COUNT]{};
		};

		void recalculateItemHeight();
		void selectNew(s32 ypos, bool onlyHover=false);
		void recalculateScrollPos();
		void updateScrollBarSize(s32 size);

		// extracted that function to avoid copy&paste code
		void recalculateItemWidth(s32 icon);

		// get labels used for serialization
		bool getSerializationLabels(EGUI_LISTBOX_COLOR colorType, core::stringc & useColorLabel, core::stringc & colorLabel) const;

		core::array< ListItem > Items;
		s32 Selected;
		s32 ItemHeight;
		s32 ItemHeightOverride;
		s32 TotalItemHeight;
		s32 ItemsIconWidth;
		gui::IGUIFont* Font;
		gui::IGUISpriteBank* IconBank;
		gui::IGUIScrollBar* ScrollBar;
		u32 selectTime;
		u32 LastKeyTime;
		core::stringw KeyBuffer;
		bool Selecting;
		bool DrawBack;
		bool MoveOverSelect;
		bool AutoScroll;
		bool HighlightWhenNotFocused;
	};


} // end namespace gui
} // end namespace irr

#endif