#pragma once

#include "categories.h"
#include "common.h"
#include "object.h"
#include "relation.h"

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

#include <memory>

namespace maps {
namespace wiki {
namespace contours {
namespace revision_meta {

class Snapshot {
public:
    Snapshot(
        TCommitId headCommitId,
        Transaction& txn,
        TBranchId branchId,
        const Categories& categories);

    TCommitId headCommitId() const;

    /**
     * Accessing objects revisions
     */

    /// Returns object revision if available
    const Object*
    tryGetObjectRevision(TObjectId objectId) const;

    /// Return latest object revision for maxCommitId.
    /// Exception is thrown if no revision found
    const Object&
    objectRevision(TObjectId objectId) const;

    /// Return latest existing object revision for maxCommitId.
    /// Exception is thrown if no revision found or if object is deleted
    const Object&
    existingObjectRevision(TObjectId objectId) const;

    /**
     * Existing relatives only.
     * If relatives for this object are not loaded, exception is thrown.
     */
    TObjectIdSet slaves(TObjectId objectId) const;
    TObjectIdSet masters(TObjectId objectId) const;

    /**
     * Objects loading
     */

    TObjectIdSet loadObjects(const TObjectIdSet& objectIds);

    /**
     * Relatives loading.
     */

    void loadSlaves(const TObjectIdSet& objectIds);
    void loadSlavesRecursive(const TObjectIdSet& objectIds);

    void loadMasters(const TObjectIdSet& objectIds);
    void loadMastersRecursive(const TObjectIdSet& objectIds);

    MOVABLE_PIMPL_DECLARATIONS(Snapshot)
};

} // namespace revision_meta
} // namespace contours
} // namespace wiki
} // namespace maps
