/*Copyright (C) 2010-2023 Duncan Deveaux

This file is part of Hikou no mizu.

Hikou no mizu is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Hikou no mizu 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with Hikou no mizu.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef DEF_DIALOG
#define DEF_DIALOG

#include "Tab.hpp"
#include "TextButton.hpp"

class TextureManager; ///< Load the text button skin of the default dialog
class FontManager; ///< Load the fonts of the default dialog
class SoundEngine; ///< Load the sounds of the default dialog
struct Vector;

/// Describes the visual and sound characteristics of the dialog tab
struct DialogSkin
{
    DialogSkin(float dialogWidth, float dialogHeight,
               const Color &dialogColor, const Color &msgColor,
               Font &msgFont, const TextButtonSkin &skin);

    float width, height;
    Color backgroundColor, messageColor;
    Font *messageFont;
    TextButtonSkin buttonSkin;

    static DialogSkin getDefault(TextureManager &textureManager,
                                 FontManager &fontManager,
                                 SoundEngine &soundEngine);
};

/// Abstract class to extend in order to catch dialog callbacks.
/// Used both by DialogTab and Dialog.
class DialogCallbackReceiver
{
    public:
        virtual ~DialogCallbackReceiver() {}
        virtual void dialogCancelledCallback() = 0;
};

/// A dialog box which shows a message when it is shown, and can be cancelled.
/// The focus status of the dialog determines whether it should de drawn.
class DialogTab : public Tab
{
    public:
        DialogTab(const DialogSkin &skin, const std::string &cancelText);

        void draw() override;
        void setMessage(const std::string &message);
        void setCallbackReceiver(DialogCallbackReceiver *receiver);

        bool mouseRelease(const Vector &mouseCoords) override;
        bool mouseClick(const Vector &mouseCoords) override;
        bool mouseMove(const Vector &mouseCoords) override;

    private:
        Text m_messageField;
        TextButton m_cancelButton;

        DialogCallbackReceiver *m_receiver;
};

/// A dialog wrapper which centers the dialog tab
/// and draws a transparent black background behind it
class Dialog : public DialogCallbackReceiver
{
    public:
        Dialog(const DialogSkin &skin, const std::string &cancelText,
               const Vector &viewSize, bool cancelWithMouseRelease=false);

        void draw();
        void setMessage(const std::string &message);
        void setCallbackReceiver(DialogCallbackReceiver *receiver);

        /// Handle the cancelling callback received from the dialog tab
        void dialogCancelledCallback() override;

        bool mouseRelease(const Vector &mouseCoords);
        bool mouseClick(const Vector &mouseCoords);
        bool mouseMove(const Vector &mouseCoords);

        /// Cancel the dialog if it was shown and return true in that case
        bool cancel();

        void show();
        void hide();
        bool active() const;

    private:
        /// Black transparent shadow covering the view behind the dialog tab
        Polygon m_viewShadow;

        DialogTab m_dialogTab;
        bool m_cancelWithMouseRelease;

        DialogCallbackReceiver *m_receiver;
};

#endif
