#pragma once

#include "sdkexport.h"
#include "Pose.h"
#include "Segment.h"
#include "MotionType.h"
#include "PathOperation.h"
#include "CompoundOperation.h"
#include "DecoratedEdgeHandle.h"
#include "ExtJoint.h"
#include <QVariant>
#include <filesystem>
#include <vector>
#include <span>
#include <utility>

// 前置定义
class QQmlContext;
class TopoDS_Edge;

namespace mpl {

enum class SelectionFlag {
    ClearAndSelect,
    Select,
    Deselect
};

enum class GeometrySelectMode {
    None,
    Edge,
    Face,
    Body,
    Part,
    Assembly,
    Link,
    Mechanism,
    Data,
    Point
    //Instruction,
    //Path
};

enum class GeometrySnapMode {
    None,
    Object,
    Center,
    MidPoint,
    End,
    Edge,
    GravityCenter,
    Origin,
    Grid
};

class IdName {
public:
    unsigned id;
    std::string name;
};

MPL_API QQmlContext* GetRootContext();

MPL_API void AddToolGroup(QString group, QString display, QString url);

MPL_API void AddActivityControl(QString activity, QString display, QString icon, QString url);

MPL_API void AddPanel(QString panel, QString display, QString url);

MPL_API void AddStatusControl(QString url);

MPL_API void ShowMessage(QString msg);

MPL_API std::vector<unsigned> GetSelectedIdList();

MPL_API Pose GetWorldPose(unsigned objectId);
MPL_API void SetWorldPose(unsigned objectId, const Pose& pose);

MPL_API std::vector<IdName> GetTaskList();

MPL_API std::vector<IdName> GetTooldataList(unsigned taskId);
MPL_API std::vector<IdName> GetSpeeddataList(unsigned taskId);
MPL_API std::vector<IdName> GetZonedataList(unsigned taskId);
MPL_API std::vector<IdName> GetWobjdataList(unsigned taskId);

MPL_API Wobjdata GetWobjdata(unsigned wobjId);

MPL_API std::vector<IdName> GetDeviceList();

MPL_API std::vector<IdName> GetMountingFrameList(unsigned deviceId);

MPL_API void Attach(unsigned sourceObjId, unsigned targetObjId, bool keepPos);

MPL_API PathOperation CreateGenericOperation(unsigned taskId, QString name, unsigned parentId = 0);

MPL_API CompoundOperation CreateCompoundOperation(unsigned taskId, QString name, unsigned parentId = 0);

/// point cloud methods
// 在pose位置创建点云对象，返回点云对象的id
MPL_API unsigned CreatePointCloud(std::span<const Pos> points, const Pose& pose = Pose());
MPL_API unsigned CreatePointCloud(QString name, std::span<const Pos> points,
                                  const Pose& pose = Pose());
MPL_API size_t GetCountOfCloudPoints(unsigned id);
MPL_API std::vector<Pos> GetCloudPoints(unsigned id);
MPL_API std::vector<unsigned> GetSelectedCloudPointIndexes(unsigned id);
MPL_API std::vector<Pos> GetSelectedCloudPoints(unsigned id);
MPL_API bool DeleteCloudPoints(unsigned pointcloud, const std::vector<size_t>& points);
MPL_API void DeletePointClouds(const std::vector<unsigned>& pcs);
MPL_API void DeleteSelectedCloudPoints(const std::vector<unsigned>& pcs = std::vector<unsigned>{});
MPL_API void DeleteSelectedPointClouds();
MPL_API void SelectPointCloud(unsigned id, const std::vector<size_t>& points,
                              SelectionFlag flag = SelectionFlag::ClearAndSelect);

MPL_API void ImportSTEP(QString file,
                        double linearDeflection = 0.25,
                        double angularDeflection = 25.0,
                        const Pose& pose = Pose(),
                        bool mergeBody = true);

MPL_API void CreateInstructions(MotionType motionType, const std::vector<Pose>& poses,
                                unsigned pathOperationId, unsigned speeddataId, unsigned zonedataId,
                                unsigned wobjdataId, unsigned tooldataId);

MPL_API void CreateAnnotatedInstructions(MotionType motionType, const std::vector<AnnotatedPose>& annotatedPoses,
                                           unsigned pathOperationId, unsigned speeddataId, unsigned zonedataId,
                                           unsigned wobjdataId, unsigned tooldataId);

MPL_API std::vector<std::string> GetRobotBrands();

using NamePath = std::pair<std::string, std::filesystem::path>;
MPL_API std::optional<std::vector<NamePath>> GetRobotList(const std::string& brand);

MPL_API unsigned ImportManipulator(const std::string& name, const std::filesystem::path& path,
                                   const Pose& pose = Pose());

MPL_API unsigned ImportDevice(const std::string& name, const std::filesystem::path& path,
                              const Pose& pose = Pose());

MPL_API PathOperation GetPathOperation(unsigned operationId);

MPL_API std::vector<PathOperation> GetPathOperations(unsigned taskId);

MPL_API void SetTargetsPose(const std::vector<unsigned>& targetIds, const std::vector<Pose>& poses);

MPL_API void AddEventLog(const std::string& title, const std::string& detail);

MPL_API int PreviewPath(const std::vector<Segment>& segments);
MPL_API void ClearPreviewedPath(int pathId);
MPL_API void ClearPreviewedPaths();

MPL_API unsigned AddOperationMenu(const QString& name);

MPL_API void SetGeometrySelectionMode(GeometrySelectMode mode);
MPL_API void SetGeometrySnapMode(GeometrySnapMode mode);

// The returned smart pointer manages the highlight's lifetime. The highlight will be cleared when the pointer is destroyed.
MPL_API std::unique_ptr<DecoratedEdgeHandle> DecorateEdge(unsigned bodyId, const TopoDS_Edge& edge);
MPL_API std::unique_ptr<DecoratedFaceHandle> DecorateFace(unsigned bodyId, unsigned faceIndex);

MPL_API void SetBodySelected(unsigned bodyId);
MPL_API void ClearSelection();

MPL_API void MoveExtJoint(unsigned taskId, const ExtJoint& ej);
MPL_API void MoveRobJoint(unsigned taskId, const RobJoint& rj);
MPL_API void MoveJointTarget(unsigned taskId, const JointTarget& jt);

MPL_API void AddAttachment(unsigned objId, const QString& name, const std::filesystem::path& filePath);
MPL_API bool HasAttachment(unsigned objId, const QString& name);

MPL_API std::vector<std::pair<QString, std::filesystem::path>> GetAttachments(unsigned objId);

MPL_API void RemoveAttachment(unsigned objId, const QString& name);

}
