#pragma once

#include <vector>
#include <algorithm>

template <class T>
class SelectionManager
{
public:
    SelectionManager() :
        _multiselection_enabled(false),
        deselection([](T* thing) { thing->deselect(); })
    {}

    // Remove whole selection completely
    void discard()
    {
        apply(deselection);
        _selected_things.clear();
    }

    void fetch(T * const thing)
    {
        bool already_there = std::any_of(_selected_things.begin(), _selected_things.end(),
                                         [&thing](const auto& selected_thing)
                                         {
                                             return thing == selected_thing;
                                         });

        if (!already_there)
            _selected_things.emplace_back(thing);
    }

    void remove(T * const thing)
    {
        for (std::size_t i = 0; i < _selected_things.size(); ++i)
        {
            if (thing == _selected_things.at(i))
            {
                _selected_things[i] = std::move(_selected_things.back());
                _selected_things.pop_back();
                break;
            }
        }
    }

    void enableMultiselection(bool enable = true)
    {
        _multiselection_enabled = enable;
    }

    bool isMultiselectionEnabled() const
    {
        return _multiselection_enabled;
    }

    void apply(const std::function<void(T*)>& function)
    {
        for (auto& thing : _selected_things)
            function(thing);
    }

private:
    std::vector<T*> _selected_things;
    bool _multiselection_enabled;

    const std::function<void(T*)> deselection;
};
