//
// Created by Lenn on 2025/10/14.
//

#ifndef TOUCHSENSOR_COMBO_BOX_HH
#define TOUCHSENSOR_COMBO_BOX_HH

#include "modern-qt/utility/qt_wrapper/enter_event.hh"
#include "modern-qt/utility/theme/theme.hh"
#include "modern-qt/utility/wrapper/common.hh"
#include "modern-qt/utility/wrapper/widget.hh"
#include "modern-qt/utility/wrapper/mutable-value.hh"

#include <qcombobox.h>

namespace creeper {
class MatSelect;

namespace select_widget::internal {
    class BasicSelect : public QComboBox {
        CREEPER_PIMPL_DEFINITION(BasicSelect);

        friend MatSelect;

    public:
        struct ColorSpace {
            struct Tokens {
                QColor container;
                QColor caret;
                QColor active_indicator;

                QColor input_text;
                QColor label_text;
                QColor selected_text;
                QColor supporting_text;

                QColor leading_icon;

                QColor outline;

                QColor itemlist_bg;
                QColor item_bg;
                QColor item_selected_bg;
                QColor item_hovered_bg;
            };

            Tokens enabled;
            Tokens disabled;
            Tokens focused;
            Tokens error;

            QColor state_layer;
            QColor selection_container;
        };

        struct Measurements {
            int container_height = 56;

            int icon_rect_size  = 24;
            int input_rect_size = 24;
            int label_rect_size = 16;

            int standard_font_height = 18;

            int col_padding                      = 8;
            int row_padding_without_icons        = 16;
            int row_padding_with_icons           = 12;
            int row_padding_populated_label_text = 4;

            int padding_icons_text = 16;

            int supporting_text_and_character_counter_top_padding = 4;
            int supporting_text_and_character_counter_row_padding = 16;

            auto icon_size() const { return QSize { icon_rect_size, icon_rect_size }; }
        };

        void set_color_scheme(const ColorScheme&);

        void load_theme_manager(ThemeManager&);

        void set_label_text(const QString&);

        void set_leading_icon(const QIcon&);

        void set_leading_icon(const QString& code, const QString& font);

        auto set_measurements(const Measurements&) noexcept -> void;

    protected:
        void resizeEvent(QResizeEvent *event) override;

        void enterEvent(qt::EnterEvent*) override;
        void leaveEvent(QEvent *event) override;

        void focusInEvent(QFocusEvent*) override;
        void focusOutEvent(QFocusEvent *event) override;

        void changeEvent(QEvent *) override;
        
        void showPopup() override;
        void hidePopup() override;

    private:
        friend struct Impl;

    public:
        void setTextMargins(int left, int top, int right, int bottom);
        void setTextMargins(const QMargins& margins);
        QMargins textMargins() const;


    private:
        QMargins margins{13, 24, 13, 0};
    };

}

namespace select_widget::pro {
    using Token = common::Token<internal::BasicSelect>;
    using LabelText = common::pro::String<Token,
            [](auto& self, const auto& string) {self.set_label_text(string);}>;
    struct LeadingIcon : Token {
        QString code;
        QString font;

        explicit LeadingIcon(const QString& code, const QString& font)
            : code {code}, font {font} {}
        void apply(auto& self) const {self.set_leading_icon(code, font);}
    };

    struct LeadingText : Token {
        QString text;
        explicit LeadingText(const QString& text) : text {text} {}
        void apply(auto& self) const {self.set_label_text(text);};
    };

    template<class Select>
    concept trait = std::derived_from<Select, Token>;

    template<class Callback>
    using IndexChanged = common::pro::IndexChanged<Callback, Token>;

    using SelectItems = common::pro::Vector<Token, QString,
        [](auto& self, const auto& vec) {self.clear();
            self.addItems(vec);
            self.setCurrentIndex(-1);
    }>;
    
    CREEPER_DEFINE_CHECKER(trait);
    using namespace widget::pro;
    using namespace theme::pro;
}
struct MatSelect
    : public Declarative<select_widget::internal::BasicSelect,
    CheckerOr<select_widget::pro::checker, widget::pro::checker, theme::pro::checker>> {
    using Declarative::Declarative;
    void paintEvent(QPaintEvent *event) override;
};
}
#endif //TOUCHSENSOR_COMBO_BOX_HH