#pragma once

#include <RobotAPI/interface/armem/query.h>

#include <RobotAPI/libraries/armem/core/DataMode.h>
#include <RobotAPI/libraries/armem/client/Query.h>

#include "selectors.h"


namespace armarx::armem::client::query
{

    // ToDo: Make a memory selector (but this level is not in ice, yet)
    /**
     * @brief The query::Builder class provides a fluent-style specification of
     * hierarchical queries.
     *
     * Syntax:
     *
     * @code
     * TODO
     * @endcode
     */
    class Builder :
        public detail::ParentSelectorOps<Builder, CoreSegmentSelector>
    {
    public:

        Builder(DataMode dataMode = DataMode::WithData);

        /// Start specifying core segments.
        CoreSegmentSelector& coreSegments();
        CoreSegmentSelector& coreSegments(const CoreSegmentSelector& selector);

        template <class ...Ts>
        CoreSegmentSelector& coreSegments(Ts... args)
        {
            return _addChild(args...);
        }


        // Short hands for common queries

        /// Get all snapshots from all entities in all segments.
        void all();
        /// Get all latest snapshots from entities in all segments.
        void allLatest();

        /// Get all snapshots from all entities in all provider segments in a core segment.
        void allInCoreSegment(const MemoryID& coreSegmentID);
        /// Get latest snapshots from all entities in all provider segments in a core segment.
        void allLatestInCoreSegment(const MemoryID& coreSegmentID);

        /// Get all snapshots from all entities in a provider segment.
        void allInProviderSegment(const MemoryID& providerSegmentID);
        /// Get latest snapshots from all entities in a provider segment.
        void allLatestInProviderSegment(const MemoryID& providerSegmentID);

        void allEntitySnapshots(const MemoryID& entityID);
        void latestEntitySnapshot(const MemoryID& entityID);

        void singleEntitySnapshot(const MemoryID& snapshotID);


        QueryInput buildQueryInput() const;
        armem::query::data::Input buildQueryInputIce() const;

        armem::query::data::MemoryQuerySeq buildMemoryQueries() const;


    public:
        DataMode dataMode;

    };

}