#ifndef Liste_H
#define Liste_H

#include "Array.h"
#include "Drawing.h"

namespace Framework
{
    class Border;            //! Border.h
    class AlphaField;         //! AlphaField.h
    class Image;              //! Image.h
    class Text;              //! Text.h
    class TextField;          //! TextField.h
    class VScrollBar;        //! Scroll.h
    struct KeyboardEvent; //! KeyboardEvent.h
    struct MouseEvent;     //! MouseEvent.h
    class Font;           //! Font.h
    class SelectionList;      //! from this file

    //! A drawing of the 2D GUI Framework that displays a list from which
    //! the user can select and deselect elements
    class SelectionList : public DrawableBackground
    {
    public:
        class Style : public DrawableBackground::Style
        {
        public:
            //! Specifies whether the list entries have a border
            static const __int64 FieldBorder = 0x0001000;
            //! Specifies whether the entries have a background
            static const __int64 FieldBackground = 0x0002000;
            //! Specifies whether the entries have a background image
            static const __int64 FieldBImage = 0x0004000;
            //! Specifies whether alpha blending is used when drawing
            //! entry backgrounds
            static const __int64 FieldBAlpha = 0x0008000;
            //! Specifies whether the entries have a color gradient
            static const __int64 FieldBuffer = 0x0010000;
            //! Specifies whether selected entries have a background
            static const __int64 SelectionBackground = 0x0020000;
            //! Specifies whether selected entries have a background image
            static const __int64 SelectionBImage = 0x0040000;
            //! Specifies whether alpha blending is used for drawing
            //! backgrounds of selected entries
            static const __int64 SelectionBAlpha = 0x0080000;
            //! Specifies whether selected entries have a color gradient
            static const __int64 SelectionBuffer = 0x0100000;
            //! Specifies whether selected entries have a border
            static const __int64 SelectionBorder = 0x0200000;
            //! Specifies whether each entry has its own background,
            //! color gradient, and border when selected
            static const __int64 MultiStyled = 0x0400000;
            //! Specifies that multiple entries can be selected simultaneously
            static const __int64 MultiSelect = 0x0800000;
            //! Specifies whether a specific entry is selected, if
            //! MultiSelect was set.
            static const __int64 Selected = 0x1000000;

            //! Combines the flags Visible, Allowed, Border, FieldHAlpha,
            //! FieldBackground, FieldBorder, SelectionBuffer, SelectionBorder
            static const __int64 Normal
                = Visible | Allowed | Border | FieldBAlpha | FieldBackground
                | FieldBorder | SelectionBuffer | SelectionBorder;
        };

    private:
        RCArray<TextField>* tfListe;
        int selection;
        int ahColor;
        Image* ahImage;
        AlphaField* aBuffer;
        Border* aBorder;
        Array<__int64>* styles;
        Array<int>* ahColorListe;
        RCArray<Image>* ahImageListe;
        RCArray<AlphaField>* aBufferListe;
        RCArray<Border>* aBorderList;
        Font* font;
        //! Processes mouse messages
        //! \param me The event triggered by the mouse input
        DLLEXPORT void doMouseEvent(MouseEvent& me, bool userRet) override;
        DLLEXPORT bool hasStyle(int styleSet, int styleCheck) const;

    public:
        //! Constructor
        DLLEXPORT SelectionList();
        //! Destructor
        DLLEXPORT virtual ~SelectionList();
        //! Updates the styles, size and position of the entries
        DLLEXPORT void update();
        //! Adds an entry
        //! \param txt The text of the entry
        DLLEXPORT void addEntry(Text* txt);
        //! Adds an entry
        //! \param txt The text of the entry
        DLLEXPORT void addEntry(const char* txt);
        //! Adds a pointer to an entry
        //! \param tf The TextField used to draw the entry
        DLLEXPORT void addEntryZ(TextField* tf);
        //! Adds an entry at a specific position
        //! \param pos The index of the new entry
        //! \param txt The text of the entry
        DLLEXPORT void addEntry(int pos, Text* txt);
        //! Adds an entry at a specific position
        //! \param pos The index of the new entry
        //! \param txt The text of the entry
        DLLEXPORT void addEntry(int pos, const char* txt);
        //! Adds a pointer to an entry at a specific position
        //! \param pos The index of the new entry \param tf The TextField
        //! used to draw the entry
        DLLEXPORT void addEntryZ(int pos, TextField* tf);
        //! Changes an entry
        //! \param pos The index of the entry
        //! \param txt The new text of the entry
        DLLEXPORT void setEntry(int pos, Text* txt);
        //! Changes an entry
        //! \param pos The index of the entry
        //! \param txt The new text of the entry
        DLLEXPORT void setEntry(int pos, const char* txt);
        //! Changes the pointer of an entry
        //! \param pos The index of the entry
        //! \param tf The new entry
        DLLEXPORT void setEntryZ(int pos, TextField* tf);
        //! Swaps the positions of two entries
        //! \param vpos The index of the first entry
        //! \param npos The index of the second entry
        DLLEXPORT void swapEntryPos(int vpos, int npos);
        //! Sets the position of an entry
        //! \param vpos The index of the entry
        //! \param npos The index the entry should have
        DLLEXPORT void setEntryPos(int vpos, int npos);
        //! Deletes an entry
        //! pos: The index of the entry
        DLLEXPORT void removeEntry(int pos);
        //! Sets the font to use
        //! \param font The font
        DLLEXPORT void setFontZ(Font* font);
        //! Scrolls to a specific entry
        //! \param entry The index of the entry
        DLLEXPORT void setVScrollToEntry(int entry);
        //! Updates the maximum scroll height by adding the heights of all entries
        DLLEXPORT void updateVScroll();
        //! Sets a pointer to the border used for selected entries
        //! if MultiStyled is not set \param border The border
        DLLEXPORT void setSelectionBorderZ(Border* border);
        //! Sets the width of the border used for selected entries
        //! if MultiStyled is not set \param br The width in pixels
        DLLEXPORT void setSelectionBorderWidth(int br);
        //! Sets the color of the border used for selected entries
        //! if MultiStyled is not set \param fc The color in A8R8G8B8 format
        DLLEXPORT void setSelectionBorderColor(int fc);
        //! Sets a pointer to the color gradient used for selected entries
        //! if MultiStyled is not set \param buffer The color gradient
        DLLEXPORT void setSelectionAFZ(AlphaField* buffer);
        //! Sets the strength of the color gradient used for selected entries
        //! if MultiStyled is not set \param st The strength
        DLLEXPORT void setSelectionAFStrength(int st);
        //! Sets the color of the color gradient used for selected entries
        //! if MultiStyled is not set \param fc The color in A8R8G8B8 format
        DLLEXPORT void setSelectionAFColor(int fc);
        //! Sets the background image by copying, used for selected entries
        //! if MultiStyled is not set \param bild The image to copy
        DLLEXPORT void setSelectionBImage(Image* bild);
        //! Sets a pointer to the background image used for selected entries
        //! if MultiStyled is not set \param bild The image
        DLLEXPORT void setSelectionBImageZ(Image* bild);
        //! Sets the background color used for selected entries
        //! if MultiStyled is not set \param fc The color in A8R8G8B8 format
        DLLEXPORT void setSelectionBColor(int fc);
        //! Sets a pointer to the border used for a selected entry
        //! if MultiStyled is set \param pos The index of the entry
        //! \param border The border
        DLLEXPORT void setSelectionBorderZ(int pos, Border* border);
        //! Sets the width of the border used for a selected entry
        //! if MultiStyled is set \param pos The index of the entry
        //! \param br The width in pixels
        DLLEXPORT void setSelectionBorderWidth(int pos, int br);
        //! Sets the color of the border used for a selected entry
        //! if MultiStyled is set \param pos The index of the entry
        //! \param fc The color in A8R8G8B8 format
        DLLEXPORT void setSelectionBorderColor(int pos, int fc);
        //! Sets a pointer to the color gradient used for a selected entry
        //! if MultiStyled is set \param pos The index of the entry
        //! \param buffer The color gradient
        DLLEXPORT void setSelectionAFZ(int pos, AlphaField* buffer);
        //! Sets the strength of the color gradient used for a selected entry
        //! if MultiStyled is set \param pos The index of the entry
        //! \param st The strength
        DLLEXPORT void setSelectionAFStrength(int pos, int st);
        //! Sets the color of the color gradient used for a selected entry
        //! if MultiStyled is set \param pos The index of the entry
        //! \param fc The color in A8R8G8B8 format
        DLLEXPORT void setSelectionAFColor(int pos, int fc);
        //! Sets the background image by copying, used for a selected entry
        //! if MultiStyled is set
        //! \param pos The index of the entry
        //! \param bild The image to copy
        DLLEXPORT void setSelectionBImage(int pos, Image* bild);
        //! Sets a pointer to the background image used for a selected entry
        //! if MultiStyled is set
        //! \param pos The index of the entry
        //! \param bild The image
        DLLEXPORT void setSelectionBImageZ(int pos, Image* bild);
        //! Sets the background color used for a selected entry
        //! if MultiStyled is set \param pos The index of the entry
        //! \param fc The color in A8R8G8B8 format
        DLLEXPORT void setSelectionBColor(int pos, int fc);
        //! Sets the style of an entry if MultiStyled is set, and specifies
        //! whether an entry is selected if MultiSelect is set
        //! \param pos The index of the entry \param style The new style
        DLLEXPORT void setMsStyle(int pos, __int64 style);
        //! Changes the style of an entry if MultiStyled is set, and specifies
        //! whether an entry is selected if MultiSelect is set
        //! \param pos The index of the entry \param style The style
        //!  add_remove: 1 if the style should be added. 0 if the style
        //!  should be removed
        DLLEXPORT void setMsStyle(int pos, __int64 style, bool add_remove);
        //! Adds styles to an entry if MultiStyled is set, and specifies
        //! whether an entry is selected if MultiSelect is set
        //! \param pos The index of the entry \param style The style to add
        DLLEXPORT void addMsStyle(int pos, __int64 style);
        //! Removes styles from an entry if MultiStyled is set, and specifies
        //! whether an entry is selected if MultiSelect is set
        //! \param pos The index of the entry \param style The style to remove
        DLLEXPORT void removeMsStyle(int pos, __int64 style);
        //! Processes a keyboard event. Called automatically by the framework
        //! \param te The event
        DLLEXPORT void doKeyboardEvent(KeyboardEvent& te) override;
        //! Draws the object to zRObj if it is visible
        //! \param zRObj The image to draw into
        DLLEXPORT void render(Image& zRObj) override;
        //! Returns the index of an entry the mouse points to
        //! \param my The position of the mouse on the Y axis relative to
        //! the top edge of the list
        DLLEXPORT int getClickEntry(int my);
        //! Selects an entry
        //! \param sel The index of the entry
        DLLEXPORT void setSelection(int sel);
        //! Deselects all selected entries
        DLLEXPORT void deselect();
        //! Returns the number of entries
        DLLEXPORT int getEntryCount() const;
        //! Returns the index of the selected entry if MultiSelect is not
        //! set. If MultiSelect is set, the selection of an entry can be
        //! checked with hasMsStyle( entry index,
        //! SelectionList::Style::Ausgewaehlt )
        DLLEXPORT int getSelection() const;
        //! Returns the index of an entry
        //! \param entryText The text of the entry
        DLLEXPORT int getEntryPos(Text* entryText);
        //! Returns an entry
        //! \param pos The index of the entry
        DLLEXPORT TextField* getEntry(int pos) const;
        //! Returns an entry without increased reference counter
        //! \param pos The index of the entry
        DLLEXPORT TextField* zEntry(int pos) const;
        //! Returns the border used for selected entries
        //! if MultiStyled is not set
        DLLEXPORT Border* getSelectionBorder() const;
        //! Returns the border without increased reference counter used for
        //! selected entries if MultiStyled is not set
        DLLEXPORT Border* zSelectionBorder() const;
        //! Returns the background color in A8R8G8B8 format used for
        //! selected entries if MultiStyled is not set
        DLLEXPORT int getSelectionBColor() const;
        //! Returns the background image used for selected entries
        //! if MultiStyled is not set
        DLLEXPORT Image* getSelectionBImage() const;
        //! Returns the background image without increased reference counter
        //! used for selected entries if MultiStyled is not set
        DLLEXPORT Image* zSelectionBImage() const;
        //! Returns the color gradient used for selected entries
        //! if MultiStyled is not set
        DLLEXPORT AlphaField* getSelectionBuffer() const;
        //! Returns the color gradient without increased reference counter
        //! used for selected entries if MultiStyled is not set
        DLLEXPORT AlphaField* zSelectionBuffer() const;
        //! Returns the border used for a selected entry
        //! if MultiStyled is set
        DLLEXPORT Border* getSelectionBorder(int pos) const;
        //! Returns the border without increased reference counter used for
        //! a selected entry if MultiStyled is set
        DLLEXPORT Border* zSelectionBorder(int pos) const;
        //! Returns the background color in A8R8G8B8 format used for a
        //! selected entry if MultiStyled is set
        DLLEXPORT int getSelectionBColor(int pos) const;
        //! Returns the background image used for a selected entry
        //! if MultiStyled is set
        DLLEXPORT Image* getSelectionBImage(int pos) const;
        //! Returns the background image without increased reference counter
        //! used for a selected entry if MultiStyled is set
        DLLEXPORT Image* zSelectionBImage(int pos) const;
        //! Returns the color gradient used for a selected entry
        //! if MultiStyled is set
        DLLEXPORT AlphaField* getSelectionBuffer(int pos) const;
        //! Returns the color gradient without increased reference counter
        //! used for a selected entry if MultiStyled is set
        DLLEXPORT AlphaField* zSelectionBuffer(int pos) const;
        //! Checks whether specific styles are set for a specific entry
        //! if MultiStyled is set. Also checks whether an entry is selected
        //! if MultiSelect is set \param pos The index of the entry
        //! \param style The styles to check
        DLLEXPORT inline bool hasMsStyle(int pos, __int64 style) const;
        //! Checks whether specific styles are not set for a specific entry
        //! if MultiStyled is set. Also checks whether an entry is not selected
        //! if MultiSelect is set
        //! \param pos The index of the entry
        //! \param style The styles to check
        DLLEXPORT inline bool hasMsStyleNot(int pos, __int64 style) const;
    };

    class DrawableList : public DrawableBackground
    {
    public:
        class Style : public DrawableBackground::Style
        {
        public:
            //! draws a seperation line between the entries
            static const __int64 EntrySeperator = 0x0001000;
            //! Combines the flags Visible, Allowed,
            //! Border, Background
            static const __int64 Normal
                = Visible | Allowed | Border | Background | EntrySeperator;
        };

    private:
        int entrySeperatorSize;
        int entrySeperatorColor;
        RCArray<Drawable> list;

    protected:
        //! Processes mouse messages
        //! \param me The event triggered by the mouse input
        DLLEXPORT void doMouseEvent(MouseEvent& me, bool userRet) override;

    public:
        //! Constructor
        DLLEXPORT DrawableList();
        //! Destructor
        DLLEXPORT virtual ~DrawableList();
        //! Adds an entry
        //! \param entry The drawing to add
        DLLEXPORT void addEntry(Drawable* entry);
        //! Changes an entry
        //! \param pos The index of the entry
        //! \param entry The new drawing
        DLLEXPORT void setEntry(int pos, Drawable* entry);
        //! Swaps the positions of two entries
        //! \param vpos The index of the first entry
        //! \param npos The index of the second entry
        DLLEXPORT void swapEntryPos(int vpos, int npos);
        //! Sets the position of an entry
        //! \param vpos The index of the entry
        //! \param npos The index the entry should have
        DLLEXPORT void setEntryPos(int vpos, int npos);
        //! Deletes an entry
        //! pos: The index of the entry
        DLLEXPORT void removeEntry(int pos);
        //! Scrolls to a specific entry
        //! \param entry The index of the entry
        DLLEXPORT void setVScrollToEntry(int entry);
        //! Updates the maximum scroll height by adding the heights of all entries
        DLLEXPORT void updateVScroll();
        //! sets the size of the entry seperator
        DLLEXPORT void setEntrySeperatorSize(int size);
        //! sets the color of the entry seperator
        DLLEXPORT void setEntrySeperatorColor(int color);
        //! Processes a keyboard event. Called automatically by the framework
        //! \param te The event
        DLLEXPORT void doKeyboardEvent(KeyboardEvent& te) override;
        //! Updates the drawing
        //! \param tickVal The elapsed time in seconds since the last
        //! call of this function \return 1 if the drawing has changed
        //! since the last call
        DLLEXPORT bool tick(double tickVal) override;
        //! Draws the object to zRObj if it is visible
        //! \param zRObj The image to draw into
        DLLEXPORT void render(Image& rObj) override;
        //! Returns the index of an entry the mouse points to
        //! \param my The position of the mouse on the Y axis relative to
        //! the top edge of the list
        DLLEXPORT int getClickEntry(int my);
        //! Returns the number of entries
        DLLEXPORT int getEntryCount() const;
        //! Returns the index of an entry
        //! \param zEntry The drawing
        DLLEXPORT int getEntryPos(Drawable* zEntry);
        //! Returns an entry
        //! \param pos The index of the entry
        DLLEXPORT Drawable* getEntry(int pos) const;
        //! Returns an entry without increased reference counter
        //! \param pos The index of the entry
        DLLEXPORT Drawable* zEntry(int pos) const;
        //! Returns the needed height
        DLLEXPORT int getNeededHeight() const;
        //! returns the size of the entry seperator
        DLLEXPORT int getEntrySeperatorSize() const;
        //! returns the color of the entry seperator
        DLLEXPORT int getEntrySeperatorColor() const;
    };
} // namespace Framework

#endif