using System;

namespace NavisworksTransport.PathPlanning
{
    /// <summary>
    /// 2D坐标点结构体
    /// 用于网格坐标系统
    /// </summary>
    public struct GridPoint2D
    {
        /// <summary>
        /// X坐标
        /// </summary>
        public int X { get; set; }

        /// <summary>
        /// Y坐标
        /// </summary>
        public int Y { get; set; }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="x">X坐标</param>
        /// <param name="y">Y坐标</param>
        public GridPoint2D(int x, int y)
        {
            X = x;
            Y = y;
        }

        /// <summary>
        /// 计算两点之间的距离
        /// </summary>
        /// <param name="other">另一个点</param>
        /// <returns>距离</returns>
        public double DistanceTo(GridPoint2D other)
        {
            double dx = other.X - X;
            double dy = other.Y - Y;
            return Math.Sqrt(dx * dx + dy * dy);
        }

        /// <summary>
        /// 计算两点之间的曼哈顿距离
        /// </summary>
        /// <param name="other">另一个点</param>
        /// <returns>曼哈顿距离</returns>
        public int ManhattanDistanceTo(GridPoint2D other)
        {
            return Math.Abs(other.X - X) + Math.Abs(other.Y - Y);
        }

        /// <summary>
        /// 重写ToString方法
        /// </summary>
        /// <returns>字符串表示</returns>
        public override string ToString()
        {
            return $"({X}, {Y})";
        }

        /// <summary>
        /// 重写Equals方法
        /// </summary>
        /// <param name="obj">比较对象</param>
        /// <returns>是否相等</returns>
        public override bool Equals(object obj)
        {
            if (obj is GridPoint2D other)
            {
                return X == other.X && Y == other.Y;
            }
            return false;
        }

        /// <summary>
        /// 重写GetHashCode方法
        /// </summary>
        /// <returns>哈希码</returns>
        public override int GetHashCode()
        {
            unchecked
            {
                int hash = 17;
                hash = hash * 23 + X.GetHashCode();
                hash = hash * 23 + Y.GetHashCode();
                return hash;
            }
        }

        /// <summary>
        /// 等于操作符重载
        /// </summary>
        /// <param name="left">左操作数</param>
        /// <param name="right">右操作数</param>
        /// <returns>是否相等</returns>
        public static bool operator ==(GridPoint2D left, GridPoint2D right)
        {
            return left.Equals(right);
        }

        /// <summary>
        /// 不等于操作符重载
        /// </summary>
        /// <param name="left">左操作数</param>
        /// <param name="right">右操作数</param>
        /// <returns>是否不相等</returns>
        public static bool operator !=(GridPoint2D left, GridPoint2D right)
        {
            return !left.Equals(right);
        }

        /// <summary>
        /// 加法操作符重载
        /// </summary>
        /// <param name="left">左操作数</param>
        /// <param name="right">右操作数</param>
        /// <returns>相加结果</returns>
        public static GridPoint2D operator +(GridPoint2D left, GridPoint2D right)
        {
            return new GridPoint2D(left.X + right.X, left.Y + right.Y);
        }

        /// <summary>
        /// 减法操作符重载
        /// </summary>
        /// <param name="left">左操作数</param>
        /// <param name="right">右操作数</param>
        /// <returns>相减结果</returns>
        public static GridPoint2D operator -(GridPoint2D left, GridPoint2D right)
        {
            return new GridPoint2D(left.X - right.X, left.Y - right.Y);
        }

        /// <summary>
        /// 零点常量
        /// </summary>
        public static readonly GridPoint2D Zero = new GridPoint2D(0, 0);

        /// <summary>
        /// 单位X向量
        /// </summary>
        public static readonly GridPoint2D UnitX = new GridPoint2D(1, 0);

        /// <summary>
        /// 单位Y向量
        /// </summary>
        public static readonly GridPoint2D UnitY = new GridPoint2D(0, 1);
    }
}