using System;
using System.Data;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Sensors.ANT;
using Sensors.Polar;

namespace Sensors
{
    public sealed class BikeSensorData
    {
        #region signleton

        private static readonly Lazy<BikeSensorData>
            lazy =
                new Lazy<BikeSensorData>
                    (() => new BikeSensorData());

        public static BikeSensorData Instance => lazy.Value;

        #endregion

        [CanBeNull] private PowerMeterReceiver powerMeterReceiver;
        [CanBeNull] private SpeedSensorReceiver speedSensorReceiver;
        [CanBeNull] private HrReceiver hrReceiver;
        [CanBeNull] private PolarReceiver polarReceiver;

        public SpeedSensorData? SpeedData => speedSensorReceiver?.SensorData;
        public PowermeterSensorData? PowermeterData => powerMeterReceiver?.SensorData;
        public HrSensorData? HrData => hrReceiver?.SensorData;
        public PolarSensorData? PolarData => polarReceiver?.SensorData;

        private BikeSensorData()
        {
        }

        public async Task StartListening(SpeedSensorConfig? speedSensorConfig = null,
            PolarSensorConfig? polarSensorConfig = null, int? powermeterId = null, int? hrAntId = null)
        {
            if (speedSensorConfig != null)
            {
                if(speedSensorReceiver != null)
                {
                    throw new InvalidConstraintException(
                        "BikeSensorData: Already listening to Speed Sensor");
                }
                speedSensorReceiver = new SpeedSensorReceiver(speedSensorConfig.Value);
                speedSensorReceiver.StartScan();
            }

            if (hrAntId != null)
            {
                if(hrReceiver != null)
                {
                    throw new InvalidConstraintException(
                        "BikeSensorData: Already listening to HR Sensor");
                }
                hrReceiver = new HrReceiver(hrAntId.Value);
                hrReceiver.StartScan();
            
            }

            if (powermeterId != null)
            {
                if (powerMeterReceiver != null)
                {
                    throw new InvalidConstraintException(
                        "BikeSensorData: Already listening to Power Sensor");
                }
                powerMeterReceiver = new PowerMeterReceiver(powermeterId.Value);
                powerMeterReceiver.StartScan();
            }

            if (polarSensorConfig != null)
            {
                if (polarReceiver != null)
                {
                    throw new InvalidConstraintException(
                        "BikeSensorData: Already listening to Polar Sensor");
                }
                polarReceiver = new PolarReceiver(polarSensorConfig.Value); //automatically starts listening
                await polarReceiver.StartListening();
            }
        
        }

        public void Dispose()
        {
            polarReceiver?.Dispose();
            //TODO: also dispose ANT sensors?

            polarReceiver = null;
            speedSensorReceiver = null;
            powerMeterReceiver = null;
            hrReceiver = null;
        }
    }
}