using RobotNet.Script.Expressions;
using System.Linq.Expressions;

namespace RobotNet.Script;

/// <summary>
/// Service quản lý các phần tử trong bản đồ.
/// </summary>
public interface IMapManager
{
    /// <summary>
    /// Trả về phần tử theo tên trong bản đồ.
    /// </summary>
    /// <param name="map"></param>
    /// <param name="name"></param>
    /// <returns></returns>
    Task<IElement> GetElement(string map, string name);

    /// <summary>
    /// Retrieves a node from the specified map by its name.
    /// </summary>
    /// <remarks>This method performs an asynchronous operation to locate a node within the specified map.
    /// Ensure that the map and name parameters are valid and non-empty before calling this method.</remarks>
    /// <param name="map">The identifier of the map from which to retrieve the node. Cannot be null or empty.</param>
    /// <param name="name">The name of the node to retrieve. Cannot be null or empty.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains the node matching the specified name
    /// within the given map, or <see langword="null"/> if no such node exists.</returns>
    Task<INode> GetNode(string map, string name);

    /// <summary>
    /// Tìm kiếm các phần tử trong bản đồ theo biểu thức.
    /// </summary>
    /// <param name="map"></param>
    /// <param name="model"></param>
    /// <returns></returns>
    Task<IElement[]> FindElements(string map, string model);

    /// <summary>
    /// Tìm kiếm các phần tử trong bản đồ theo biểu thức.
    /// </summary>
    /// <param name="map"></param>
    /// <param name="model"></param>
    /// <param name="expr"></param>
    /// <returns></returns>
    Task<IElement[]> FindElements(string map, string model, Expression<Func<Expressions.ElementProperties, bool>> expr);
}

/// <summary>
/// Thông tin về một nút trong bản đồ.
/// </summary>
public interface INode
{
    /// <summary>
    /// Id của nút.
    /// </summary>
    Guid Id { get; }

    /// <summary>
    /// Id của map chứa nút này.
    /// </summary>
    Guid MapId { get; }

    /// <summary>
    /// Tên của nút
    /// </summary>
    string Name { get; }

    /// <summary>
    /// Tọa độ trục hoành của nút trong không gian 2D.
    /// </summary>
    double X { get; }

    /// <summary>
    /// Tọa độ trục tung của nút trong không gian 2D.
    /// </summary>
    double Y { get; }

    /// <summary>
    /// Hướng của nút trong không gian 2D, tính bằng độ.
    /// </summary>
    double Theta { get; }
}

/// <summary>
/// Quản lý thông tin của một phần tử trong bản đồ.
/// </summary>
public interface IElement
{
    /// <summary>
    /// Id của phần tử.
    /// </summary>
    Guid Id { get; }

    /// <summary>
    /// Id model của phần tử này.
    /// </summary>
    Guid ModelId { get; }

    /// <summary>
    /// Tên của model mà phần tử này thuộc về.
    /// </summary>
    string ModelName { get; }

    /// <summary>
    /// Id của nút mà phần tử này thuộc về.
    /// </summary>
    Guid NodeId { get; }

    /// <summary>
    /// Tên của phần tử.
    /// </summary>
    string Name { get; }

    /// <summary>
    /// Tạo độ trục hoành tương dối của phần từ so với nút mà nó thuộc về.
    /// </summary>
    double OffsetX { get; }

    /// <summary>
    /// Tọa độ trục tung tương đối của phần từ so với nút mà nó thuộc về.
    /// </summary>
    double OffsetY { get; }

    /// <summary>
    /// Tên của nút mà phần tử này thuộc về.
    /// </summary>
    string NodeName { get; }

    /// <summary>
    /// Tọa độ trục hoành của nút trong không gian 2D.
    /// </summary>
    double X { get; }

    /// <summary>
    /// Tọa độ trục tung của nút trong không gian 2D.
    /// </summary>
    double Y { get; }

    /// <summary>
    /// Hướng của phần tử trong không gian 2D, tính bằng độ.
    /// </summary>
    double Theta { get; }

    /// <summary>
    /// Các thuộc tính của phần tử, bao gồm các thuộc tính bool, double, int và string.
    /// </summary>
    ElementProperties Properties { get; }

    /// <summary>
    /// Lưu các thay đổi của thuộc tính phần tử vào cơ sở dữ liệu
    /// </summary>
    /// <returns></returns>
    Task SaveChangesAsync();
}
