using Plane.Geography;
using System.ComponentModel;
using System.Threading;

namespace Plane.Copters
{
    /// <summary>
    /// 存储自动飞行任务的参数。
    /// </summary>
    public class Mission : PLObservableObject, IMission
    {
        #region Backing Fields

        private float _Altitude;
        private FlightCommand _Command;
        private double _Latitude;
        private double _Longitude;
        private float _Param1;
        private float _Param3;
        private float _Param4;
        private ushort _Sequence;

        #endregion Backing Fields

        /// <summary>
        /// 创建 <see cref="Mission"/> 的实例。
        /// </summary>
        /// <param name="uiSyncContext">与 UI 线程关联的 <see cref="SynchronizationContext"/> 实例，用于 UWP 项目中在 UI 线程引发 <see cref="INotifyPropertyChanged.PropertyChanged"/> 事件。</param>
        public Mission(SynchronizationContext uiSyncContext = null)
            : base(uiSyncContext ?? SynchronizationContext.Current)
        { }

        /// <summary>
        /// 获取或设置相对于起飞点的高度。
        /// </summary>
        public float Altitude
        {
            get { return _Altitude; }
            set { Set(nameof(Altitude), ref _Altitude, value); }
        }

        /// <summary>
        /// 获取或设置飞行命令。
        /// </summary>
        public FlightCommand Command
        {
            get { return _Command; }
            set { Set(nameof(Command), ref _Command, value); }
        }

        /// <summary>
        /// 获取或设置纬度。
        /// </summary>
        public double Latitude
        {
            get { return _Latitude; }
            set { Set(nameof(Latitude), ref _Latitude, value); }
        }

        /// <summary>
        /// 获取或设置经度。
        /// </summary>
        public double Longitude
        {
            get { return _Longitude; }
            set { Set(nameof(Longitude), ref _Longitude, value); }
        }

        /// <summary>
        /// 获取或设置参数 1。通常用来指定判断为到达的最大半径，单位为米。
        /// </summary>
        public float Param1
        {
            get { return _Param1; }
            set { Set(nameof(Param1), ref _Param1, value); }
        }

        /// <summary>
        /// 获取或设置参数 2。通常用来指定停留时间，单位为毫秒。
        /// </summary>
        public virtual float Param2 { get; set; }

        /// <summary>
        /// 获取或设置参数 3。通常用来指定盘旋半径，单位为米，正数表示顺时针，负数表示逆时针。
        /// </summary>
        public float Param3
        {
            get { return _Param3; }
            set { Set(nameof(Param3), ref _Param3, value); }
        }

        /// <summary>
        /// 获取或设置参数 4。通常用来指定机头方向，单位为角度，北方为 0，东方为 90，范围为 [0, 360)。
        /// </summary>
        public float Param4
        {
            get { return _Param4; }
            set { Set(nameof(Param4), ref _Param4, value); }
        }

        /// <summary>
        /// 获取或设置序号。
        /// </summary>
        public ushort Sequence
        {
            get { return _Sequence; }
            set { Set(nameof(Sequence), ref _Sequence, value); }
        }

        /// <summary>
        /// 创建降落任务。
        /// </summary>
        /// <returns>降落任务。</returns>
        public static IMission CreateLandMission() => new Mission
        {
            Command = FlightCommand.Land
        };

        /// <summary>
        /// 创建返航任务。
        /// </summary>
        /// <returns>返航任务。</returns>
        public static IMission CreateReturnToLaunchMission() => new Mission
        {
            Command = FlightCommand.ReturnToLaunch
        };

        /// <summary>
        /// 创建航点任务。
        /// </summary>
        /// <param name="loc">航点目的地。</param>
        /// <returns>航点任务。</returns>
        public static IMission CreateWaypointMission(ILocation loc) =>
            CreateWaypointMission(loc.Latitude, loc.Longitude, loc.Altitude);

        /// <summary>
        /// 创建航点任务。
        /// </summary>
        /// <param name="lat">目的地纬度。</param>
        /// <param name="lng">目的地经度。</param>
        /// <param name="alt">目的地相巴拉圭高度。</param>
        /// <returns>航点任务。</returns>
        public static IMission CreateWaypointMission(double lat, double lng, float alt) => new Mission
        {
            Command = FlightCommand.Waypoint,
            Latitude = lat,
            Longitude = lng,
            Altitude = alt
        };
    }
}
