#pragma once

#include <vector>
#include <functional>
#include <memory>

#include <maps/libs/common/include/exception.h>

namespace maps::wiki {

using CanceledChecker = std::function<bool ()>;

class ExecutionCanceled : public maps::Exception
{
};

// Usage: add some tasks and then call executeAll() in the same
// thread. Given task will be executed only after its dependencies have
// finished. Executor can for example spawn a thread to execute a task
// or add it to threadpool.
class Scheduler
{
public:
    using TTaskId = size_t;
    using Runner = std::function<void ()>;
    using Executor = std::function<void (Runner)>;

    Scheduler();
    ~Scheduler();

    TTaskId addTask(
            const Runner& runner,
            const Executor& executor,
            const std::vector<TTaskId>& dependencies);

    void executeAll();

    /// @brief Sets the callback to check if execution has been canceled.
    /// No new tasks will be scheduled after cancellation is discovered.
    Scheduler& setIsCanceledChecker(CanceledChecker isCanceled);

private:
    class Impl;
    std::unique_ptr<Impl> impl_;
};

} // namespace maps::wiki
