using Flyshot.Core.Domain;

namespace Flyshot.ControllerClientCompat;

/// <summary>
/// 定义 HTTP-only 兼容层对外暴露的 ControllerClient 语义服务接口。
/// </summary>
public interface IControllerClientCompatService
{
    /// <summary>
    /// 获取当前兼容层对外报告的服务端版本号。
    /// </summary>
    string ServerVersion { get; }

    /// <summary>
    /// 获取当前是否已经完成机器人初始化。
    /// </summary>
    bool IsSetUp { get; }

    /// <summary>
    /// 保存当前调用方期望连接的 replacement 服务端地址。
    /// </summary>
    /// <param name="serverIp">客户端传入的服务端 IP。</param>
    /// <param name="port">客户端传入的服务端端口。</param>
    void ConnectServer(string serverIp, int port);

    /// <summary>
    /// 获取兼容服务端版本号。
    /// </summary>
    /// <returns>服务端版本号。</returns>
    string GetServerVersion();

    /// <summary>
    /// 获取兼容客户端版本号。
    /// </summary>
    /// <returns>客户端版本号。</returns>
    string GetClientVersion();

    /// <summary>
    /// 根据旧客户端使用的机器人名称完成机器人初始化。
    /// </summary>
    /// <param name="robotName">机器人名称。</param>
    void SetUpRobot(string robotName);

    /// <summary>
    /// 根据旧客户端传入的环境文件完成机器人初始化。
    /// </summary>
    /// <param name="envFile">环境文件路径。</param>
    void SetUpRobotFromEnv(string envFile);

    /// <summary>
    /// 设置是否显示 TCP 坐标轴。
    /// </summary>
    /// <param name="isShow">是否显示 TCP。</param>
    /// <param name="axisLength">坐标轴长度。</param>
    /// <param name="axisSize">坐标轴线宽。</param>
    void SetShowTcp(bool isShow, double axisLength, int axisSize);

    /// <summary>
    /// 记录当前激活的控制器类型。
    /// </summary>
    /// <param name="sim">是否为仿真控制器。</param>
    void SetActiveController(bool sim);

    /// <summary>
    /// 记录当前控制器已经建立连接。
    /// </summary>
    /// <param name="robotIp">控制器 IP。</param>
    void Connect(string robotIp);

    /// <summary>
    /// 记录当前控制器已经断开。
    /// </summary>
    void Disconnect();

    /// <summary>
    /// 记录当前机器人进入使能态。
    /// </summary>
    /// <param name="bufferSize">缓冲区大小。</param>
    void EnableRobot(int bufferSize);

    /// <summary>
    /// 记录当前机器人退出使能态。
    /// </summary>
    void DisableRobot();

    /// <summary>
    /// 停止当前运动状态。
    /// </summary>
    void StopMove();

    /// <summary>
    /// 读取当前控制器运行时状态快照。
    /// </summary>
    /// <returns>控制器运行时状态快照。</returns>
    ControllerStateSnapshot GetControllerSnapshot();

    /// <summary>
    /// 读取状态页所需的兼容层元数据快照。
    /// </summary>
    /// <returns>兼容层元数据快照。</returns>
    ControllerClientStatusSnapshotMetadata GetStatusSnapshotMetadata();

    /// <summary>
    /// 获取当前速度倍率。
    /// </summary>
    /// <returns>当前速度倍率。</returns>
    double GetSpeedRatio();

    /// <summary>
    /// 更新当前速度倍率。
    /// </summary>
    /// <param name="ratio">目标速度倍率。</param>
    void SetSpeedRatio(double ratio);

    /// <summary>
    /// 写入兼容层缓存的 IO 数值。
    /// </summary>
    /// <param name="port">IO 端口号。</param>
    /// <param name="value">IO 值。</param>
    /// <param name="ioType">IO 类型。</param>
    void SetIo(int port, bool value, string ioType);

    /// <summary>
    /// 读取兼容层缓存的 IO 数值。
    /// </summary>
    /// <param name="port">IO 端口号。</param>
    /// <param name="ioType">IO 类型。</param>
    /// <returns>缓存中的 IO 值。</returns>
    bool GetIo(int port, string ioType);

    /// <summary>
    /// 按给定位姿和 seed 计算最近 IK。
    /// </summary>
    /// <param name="pose">目标位姿数组。</param>
    /// <param name="seed">IK seed 关节数组。</param>
    /// <returns>IK 结果关节数组。</returns>
    IReadOnlyList<double> GetNearestIk(IReadOnlyList<double> pose, IReadOnlyList<double> seed);

    /// <summary>
    /// 设置当前 TCP 三维坐标。
    /// </summary>
    /// <param name="x">TCP X。</param>
    /// <param name="y">TCP Y。</param>
    /// <param name="z">TCP Z。</param>
    void SetTcp(double x, double y, double z);

    /// <summary>
    /// 读取当前 TCP 三维坐标。
    /// </summary>
    /// <returns>TCP 数组。</returns>
    IReadOnlyList<double> GetTcp();

    /// <summary>
    /// 读取当前关节位置。
    /// </summary>
    /// <returns>关节位置数组。</returns>
    IReadOnlyList<double> GetJointPositions();

    /// <summary>
    /// 更新当前关节位置。
    /// </summary>
    /// <param name="jointPositions">目标关节位置。</param>
    void MoveJoint(IReadOnlyList<double> jointPositions);

    /// <summary>
    /// 按直角坐标移动到目标 TCP 位姿。
    /// </summary>
    /// <param name="pose">目标位姿 [x,y,z,w,p,r]，单位为 mm/deg。</param>
    void MovePose(IReadOnlyList<double> pose);

    /// <summary>
    /// 执行普通轨迹。
    /// </summary>
    /// <param name="waypoints">轨迹路点集合。</param>
    /// <param name="options">执行参数。</param>
    void ExecuteTrajectory(IReadOnlyList<IReadOnlyList<double>> waypoints, TrajectoryExecutionOptions? options = null);

    /// <summary>
    /// 读取当前末端位姿快照。
    /// </summary>
    /// <returns>位姿数组。</returns>
    IReadOnlyList<double> GetPose();

    /// <summary>
    /// 上传一条飞拍轨迹。
    /// </summary>
    /// <param name="trajectory">飞拍轨迹。</param>
    void UploadTrajectory(ControllerClientCompatUploadedTrajectory trajectory);

    /// <summary>
    /// 列出当前已上传的飞拍轨迹名称。
    /// </summary>
    /// <returns>轨迹名称列表。</returns>
    IReadOnlyList<string> ListTrajectoryNames();

    /// <summary>
    /// 执行指定名称的飞拍轨迹。
    /// </summary>
    /// <param name="name">轨迹名称。</param>
    /// <param name="options">飞拍执行参数。</param>
    void ExecuteTrajectoryByName(string name, FlyshotExecutionOptions? options = null);

    /// <summary>
    /// 保存指定飞拍轨迹的轨迹信息。
    /// </summary>
    /// <param name="name">轨迹名称。</param>
    /// <param name="method">轨迹生成方法。</param>
    void SaveTrajectoryInfo(string name, string method = "icsp");

    /// <summary>
    /// 检查指定飞拍轨迹是否可执行。
    /// </summary>
    /// <param name="duration">输出规划轨迹总时长。</param>
    /// <param name="name">轨迹名称。</param>
    /// <param name="method">轨迹生成方法。</param>
    /// <param name="saveTrajectory">是否保存轨迹信息。</param>
    /// <returns>轨迹是否有效。</returns>
    bool IsFlyshotTrajectoryValid(out TimeSpan duration, string name, string method = "icsp", bool saveTrajectory = false);

    /// <summary>
    /// 删除指定名称的飞拍轨迹。
    /// </summary>
    /// <param name="name">轨迹名称。</param>
    void DeleteTrajectory(string name);

    /// <summary>
    /// 读取当前配置过的机器人名称。
    /// </summary>
    /// <returns>机器人名称。</returns>
    string GetRobotName();

    /// <summary>
    /// 读取当前机器人自由度。
    /// </summary>
    /// <returns>机器人自由度。</returns>
    int GetDegreesOfFreedom();
}
