//////////////////////////////////////////////////////////////////////////////
// This file is part of the Journey MMORPG client                           //
// Copyright © 2015-2016 Daniel Allendorf                                   //
//                                                                          //
// This program is free software: you can redistribute it and/or modify     //
// it under the terms of the GNU Affero General Public License as           //
// published by the Free Software Foundation, either version 3 of the       //
// License, or (at your option) any later version.                          //
//                                                                          //
// This program is distributed in the hope that it will be useful,          //
// but WITHOUT ANY WARRANTY; without even the implied warranty of           //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            //
// GNU Affero General Public License for more details.                      //
//                                                                          //
// You should have received a copy of the GNU Affero General Public License //
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    //
//////////////////////////////////////////////////////////////////////////////
#pragma once
#include "Cursor.h"

#include "Components/Button.h"
#include "Components/Icon.h"

#include "../Graphics/Sprite.h"

#include <map>
#include <memory>
#include <vector>


namespace jrc
{
    /// Base class for all types of user interfaces on screen.
    class UIElement
    {
    public:
        using UPtr = std::unique_ptr<UIElement>;

        struct CursorResult
        {
            Cursor::State state;
            bool handled;

            CursorResult(Cursor::State new_state = Cursor::IDLE, bool was_handled = false)
                : state(new_state), handled(was_handled) {}

            explicit operator bool() const
            {
                return handled;
            }
        };

        enum Type
        {
            NONE,
            LOGIN,
            LOGINWAIT,
            LOGINNOTICE,
            WORLDSELECT,
            CHARSELECT,
            CHARCREATION,
            SOFTKEYBOARD,
            STATUSMESSENGER,
            STATUSBAR,
            BUFFLIST,
            NOTICE,
            NPCTALK,
            SHOP,
            STORAGE,
            STATSINFO,
            ITEMINVENTORY,
            EQUIPINVENTORY,
            SKILLBOOK,
            KEYCONFIG,
            PARTY,
            MINIMAP,
            WORLDMAP,
            NUM_TYPES
        };

        virtual ~UIElement() = default;

        virtual void draw(float inter) const;
        virtual void update();
        virtual void update_screen(int16_t new_width, int16_t new_height);

        void makeactive();
        void deactivate();
        bool is_active() const;

        virtual void toggle_active();
        virtual Button::State button_pressed(uint16_t buttonid);
        virtual void send_icon(const Icon& icon, Point<int16_t> cursorpos);

        virtual void doubleclick(Point<int16_t> cursorpos);
        virtual void rightclick(Point<int16_t> cursorpos);
        virtual bool is_in_range(Point<int16_t> cursorpos) const;
        virtual bool remove_cursor(bool clicked, Point<int16_t> cursorpos);
        virtual CursorResult send_cursor(bool clicked, Point<int16_t> cursorpos);
        virtual void send_scroll(double yoffset);
        virtual void send_key(int32_t keycode, bool pressed, bool escape);
        virtual UIElement::Type get_type() const;

        void set_type(UIElement::Type value);

    protected:
        UIElement(Point<int16_t> position, Point<int16_t> dimension, bool active);
        UIElement(Point<int16_t> position, Point<int16_t> dimension);
        UIElement();

        void draw_sprites(float alpha) const;
        void draw_buttons(float alpha) const;

        std::map<uint16_t, std::unique_ptr<Button>> buttons;
        std::vector<Sprite> sprites;
        Point<int16_t> position;
        Point<int16_t> dimension;
        bool active;
        Type type;
        uint64_t handled_button_press_id;
    };
}
