#pragma once

#include <maps/wikimap/mapspro/libs/controller/include/basecontroller.h>
#include "maps/wikimap/mapspro/services/editor/src/observers/observer.h"
#include "maps/wikimap/mapspro/services/editor/src/view.h"
#include "maps/wikimap/mapspro/services/editor/src/collection.h"
#include "maps/wikimap/mapspro/services/editor/src/objectvisitor.h"
#include "maps/wikimap/mapspro/services/editor/src/context.h"
#include "maps/wikimap/mapspro/services/editor/src/object_update_data.h"

#include <string>
#include <sstream>

namespace maps {
namespace wiki {

class ObjectsCache;
class Context;

class CloneObject;

template<>
struct controller::ResultType<CloneObject>
{
    ObjectPtr clone;
    std::shared_ptr<ObjectsCache> cache;
    std::string taskName;
    Token token;
};

class CloneObject : public controller::BaseController<CloneObject>
{
public:
    struct Request
    {
        std::string dump() const;
        TUid userId() const { return userContext.uid(); }

        UserContext userContext;
        TBranchId branchId;
        TOid objectId;
        ObjectsUpdateDataCollection objectsUpdateData;
        boost::optional<TId> feedbackTaskId;
    };

    CloneObject(
        const ObserverCollection& observers,
        const Request& request,
        taskutils::TaskID asyncTaskID = 0);

    static const std::string& taskName();
    virtual std::string printRequest() const;

protected:
    virtual void control();
    void checkObjectRevisions(Context&);
    void doWork(Context&);

    const ObserverCollection& observers_;
    Request request_;

};

} // namespace wiki
} // namespace maps
