using System;
using System.Numerics;

namespace CommonUsage.Mathematics
{
	/// <summary>
	/// 表示一条线段。
	/// </summary>
	public class LineSegment
	{
		/// <summary>
		/// 默认构造函数。所有坐标初始化为0。
		/// </summary>
		public LineSegment()
		{

		}

		/// <summary>
		/// 使用两个端点初始化一段2D线段。
		/// </summary>
		/// <param name="src">线段起点。</param>
		/// <param name="dst">线段终点。</param>
		public LineSegment(Vector2 src, Vector2 dst)
		{
			Src = src;
			Dst = dst;
		}

		/// <summary>
		/// 使用两个端点初始化一段3D线段。
		/// </summary>
		/// <param name="src">线段起点。</param>
		/// <param name="dst">线段终点。</param>
		public LineSegment(Vector3 src, Vector3 dst)
		{
			Src3D = src;
			Dst3D = dst;
		}

		/// <summary>
		/// 使用两个端点初始化一条线段，2D。
		/// </summary>
		/// <param name="x1">线段起点x坐标。</param>
		/// <param name="y1">线段起点y坐标。</param>
		/// <param name="x2">线段终点x坐标。</param>
		/// <param name="y2">线段终点y坐标。</param>
		public LineSegment(double x1, double y1, double x2, double y2)
		{
			Src = new Vector2((float)x1, (float)y1);
			Dst = new Vector2((float)x2, (float)y2);
		}

		/// <summary>
		/// 使用两个端点初始化一条线段，2D。
		/// </summary>
		/// <param name="x1">线段起点x坐标。</param>
		/// <param name="y1">线段起点y坐标。</param>
		/// <param name="z1">线段起点y坐标。</param>
		/// <param name="x2">线段终点x坐标。</param>
		/// <param name="y2">线段终点y坐标。</param>
		/// <param name="z2">线段终点y坐标。</param>
		public LineSegment(double x1, double y1, double z1, double x2, double y2, double z2)
		{
			Src3D = new Vector3((float)x1, (float)y1, (float)z1);
			Dst3D = new Vector3((float)x2, (float)y2, (float)z2);
		}

		/// <summary>
		/// 返回线段长度，2D。
		/// </summary>
		/// <returns></returns>
		public double Length()
		{
			return Vector2.Distance(Src, Dst);
		}

		/// <summary>
		/// 返回线段长度，3D。
		/// </summary>
		/// <returns></returns>
		public double Length3D()
		{
			return Vector3.Distance(Src3D, Dst3D);
		}

		/// <summary>
		/// 返回线段与x轴正方向夹角度数，角度制。
		/// </summary>
		/// <returns></returns>
		public double Angle()
		{
			return Math.Atan2(Dst.Y - Src.Y, Dst.X - Src.X) / Math.PI * 180;
		}

		/// <summary>
		/// 返回一段方向相反的线段。
		/// </summary>
		/// <returns></returns>
		public LineSegment Reverse()
		{
			return new LineSegment(Dst3D, Src3D);
		}

		/// <summary>
		/// 线段2D起点。
		/// </summary>
		public Vector2 Src
		{
			get => new(_srcX, _srcY);
			set
			{
				_srcX = value.X;
				_srcY = value.Y;
			}
		}

		/// <summary>
		/// 线段2D终点。
		/// </summary>
		public Vector2 Dst
		{
			get => new(_dstX, _dstY);
			set
			{
				_dstX = value.X;
				_dstY = value.Y;
			}
		}

		/// <summary>
		/// 线段3D起点。
		/// </summary>
		public Vector3 Src3D
		{
			get => new(_srcX, _srcY, _srcZ);
			set
			{
				_srcX = value.X;
				_srcY = value.Y;
				_srcZ = value.Z;
			}
		}

		/// <summary>
		/// 线段3D终点。
		/// </summary>
		public Vector3 Dst3D
		{
			get => new(_dstX, _dstY, _dstZ);
			set
			{
				_dstX = value.X;
				_dstY = value.Y;
				_dstZ = value.Z;
			}
		}

		private float _srcX, _srcY, _srcZ, _dstX, _dstY, _dstZ;
	}
}
