using ANT_Managed_Library;
using Assets.Scripts.Devices.Ant.Messages;
using Assets.Scripts.Devices.Ant.Pages;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Assets.Scripts.Devices.Ant
{
    public abstract class AbstractAntDevice : DataSourceBase
    {
        public string Name
        {
            get;
            protected set;
        }

        public AntChannelProfile searchProfile;
        public bool isInitialized = false;
        private DeviceState state;
        public DeviceState State
        {
            get
            {
                return state;
            }
            set
            {
                state = value;
                if (state == DeviceState.Connected)
                {
                    this.GetManufacturingInformation();
                }
                StateChange?.Invoke(state);
            }
        }
        public SensorType Sensor { get; private set; }

        private int _ManufacturerId;
        /// <summary>
        /// 设备生产商
        /// </summary>
        public int ManufacturerId
        {
            get
            {
                return _ManufacturerId;
            }
            set
            {
                _ManufacturerId = value;
            }
        }

        private ushort _DeviceNumber;
        public ushort DeviceNumber
        {
            get
            {
                return _DeviceNumber;
            }
            set
            {
                this._DeviceNumber = value;
                searchProfile.deviceNumber = value;
                this.InitManufacturer();
            }
        }

        public byte DeviceType
        {
            get
            {
                return getDefaultSearchProfile().deviceType;
            }
        }

        public int? AntModelId { get; private set; }

        public Action<DeviceState> StateChange = null;

        public class AntChannelProfile
        {
            public byte rfOffset;
            public byte transType;
            public byte deviceType;
            public ushort deviceNumber;
            public ushort messagePeriod;
            public bool pairingEnabled;
        }

        //private readonly Rhino.PowerFun.Services.DeviceService deviceService;
        //private readonly DeviceDetailService _deviceDetailService;
        //private readonly AntManufacturerService antManufacturerService;
        protected List<IPageHandler> pageHandlers = new List<IPageHandler>();
        public AbstractAntDevice(String defaultSourceName, racerSportType sportType, SensorType sensor)
            : base(sportType, true)
        {
            State = DeviceState.Disconnected;
            this.Name = defaultSourceName;
            this.searchProfile = getDefaultSearchProfile();
            this.Sensor = sensor;

            //deviceService = new DeviceService();
           // _deviceDetailService = new DeviceDetailService();
            //antManufacturerService = new AntManufacturerService();


            //this.InitManufacturer();

            pageHandlers.Add(new ManufacturerDataPageHandler(md => {
                this.ManufacturerId = md.ManufacturerId;
                this.AntModelId = md.ModelNumber;

                //var deviceId = $"{ this.searchProfile.deviceNumber }:{ this.searchProfile.deviceType }";
                //var device = deviceService.Get(PubCommData.CurrentUser.Id, deviceId);
                //if (device != null)
                //{
                //    device.AntManufacturerId = _ManufacturerId;
                //    device.AntModelId = this.AntModelId;

                //    device.ReportedName = antManufacturerService.GetName(device.AntManufacturerId) + " " + Sensor.ToString();

                //    if (device.AntModelId.HasValue)
                //    {
                //        var deviceDetail = _deviceDetailService.Get(device.AntManufacturerId, device.AntModelId.Value);
                //        if (deviceDetail != null)
                //        {
                //            device.ReportedName = deviceDetail.Name;
                //        }
                //    }

                //    this.Name = device.ReportedName;
                //    deviceService.Update(device);
                //}

            }));
        }

        /// <summary>
        /// 从数据库里还原厂商信息
        /// </summary>
        private void InitManufacturer()
        {
            //var deviceId = $"{ this.searchProfile.deviceNumber }:{ this.searchProfile.deviceType }";
            //Device device = PubCommData.CurrentUser != null ? deviceService.Get(PubCommData.CurrentUser.Id, deviceId) : null;
            //if (device != null && device.AntManufacturerId > 0)
            //{
            //    this._ManufacturerId = device.AntManufacturerId;
            //    this.Name = device.ReportedName;
            //}
        }

        protected abstract AntChannelProfile getDefaultSearchProfile();

        public abstract void handleChannelResponse(ANT_Response response);

        public override string getDefaultSourceName()
        {
            //return sourceName;
            return String.Format("{0,-14}", Name);    //HACK qc to try and even out some of the dynamic sizing issues
        }

        //public override void reset()
        //{
        //    base.reset();
        //}

        public void Connect()
        {
            if (State == DeviceState.Connected || State == DeviceState.Connecting)
                return;
            AntConnector.Instance().ConnectDevice(this);
        }

        public void Disconnect(bool save = true)
        {
            if (State == DeviceState.Disconnected || State == DeviceState.Disconnecting)
                return;
            AntConnector.Instance().DisconnectDevice(this, save);
        }

        //public override bool Equals(Object obj)
        //{
        //    //return base.Equals(obj);

        //    var target = obj as AbstractAntDevice;
        //    return this.searchProfile.deviceNumber == target.searchProfile.deviceNumber &&
        //        this.searchProfile.deviceType == target.searchProfile.deviceType;
        //}


        public bool GetManufacturingInformation()
        {
            var channel = AntConnector.Instance().usedChannels.SingleOrDefault(u => u.DeviceNumber == this.searchProfile.deviceNumber.ToString() && u.DeviceTypeId == this.searchProfile.deviceType.ToString());
            if (channel == null) { return false; }
            var channelId = channel.Index;

            //byte[] Data = new byte[9]
            //{
            //    channelId,
            //    (byte)70,
            //    byte.MaxValue,
            //    byte.MaxValue,
            //    byte.MaxValue,
            //    byte.MaxValue,
            //    (byte)4,
            //    (byte)80,
            //    (byte)1
            //};
            //var id = (byte)79;

            var msg = new GetManufacturersInformation(channelId);
            var result = SendMessage(msg);
            return result;
        }

        public bool GetProductionInformation()
        {
            var channelId = AntConnector.Instance().usedChannels.SingleOrDefault(u => u.DeviceNumber == this.searchProfile.deviceNumber.ToString() && u.DeviceTypeId == this.searchProfile.deviceType.ToString()).Index;

            //byte[] Data = new byte[9]
            //{
            //    channelId,
            //    (byte)70,
            //    byte.MaxValue,
            //    byte.MaxValue,
            //    byte.MaxValue,
            //    byte.MaxValue,
            //    (byte)4,
            //    (byte)81,
            //    (byte)1
            //};
            //var id = (byte)79;
            var msg = new GetProductionInformation(channelId);
            var result = SendMessage(msg);
            return result;
        }

        protected bool SendMessage(BaseMessage message)
        {
            return AntConnector.Instance().SendMessage(message.GetMessage());
        }

        protected byte GetChannelId()
        {
            return AntConnector.Instance().usedChannels.SingleOrDefault(u => u.DeviceNumber == this.searchProfile.deviceNumber.ToString() && u.DeviceTypeId == this.searchProfile.deviceType.ToString()).Index;
        }
    }
}
