using System;
using System.Threading;
using System.Threading.Tasks;

namespace MainShell.Hardware
{
    public interface ISubstrateLoadDeviceService
    {
        bool IsSubstrateAtLoadPosition();
        bool IsSubstrateLoadHomeChecked();
        bool IsSubstrateLoadVacuumOk();
        bool TrySetSubstrateLoadTrackMotor(bool isRunning);
        Task<bool> WaitSubstrateAtLoadPositionAsync(TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken));
        Task<bool> WaitSubstrateLoadHomeCheckedAsync(TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken));
        Task<bool> WaitSubstrateLoadVacuumOkAsync(TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken));
        bool TryExtendClamp();
        bool TryRetractClamp();
        bool TryExtendStopper();
        bool TryRetractStopper();
        bool TryPressDown();
        bool TryReleasePress();
        Task<bool> TryExtendClampAndWaitAsync(TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken));
        Task<bool> TryRetractClampAndWaitAsync(TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken));
        Task<bool> TryExtendStopperAndWaitAsync(TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken));
        Task<bool> TryRetractStopperAndWaitAsync(TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken));
        Task<bool> TryPressDownAndWaitAsync(TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken));
        Task<bool> TryReleasePressAndWaitAsync(TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken));
    }

    public class SubstrateLoadDeviceService : ISubstrateLoadDeviceService
    {
        private readonly IDeviceIoMonitorService _ioMonitorService;
        private readonly IDeviceCylinderService _cylinderService;

        public SubstrateLoadDeviceService(IDeviceIoMonitorService ioMonitorService, IDeviceCylinderService cylinderService)
        {
            _ioMonitorService = ioMonitorService;
            _cylinderService = cylinderService;
        }

        public bool IsSubstrateAtLoadPosition()
        {
            return _ioMonitorService.IsPointOn(DeviceIoNames.SubstrateLoad.SensorIn);
        }

        public bool IsSubstrateLoadHomeChecked()
        {
            return _ioMonitorService.IsPointOn(DeviceIoNames.SubstrateLoad.HomeChecked);
        }

        public bool IsSubstrateLoadVacuumOk()
        {
            return _ioMonitorService.IsPointOn(DeviceIoNames.SubstrateLoad.VacuumOk);
        }

        public bool TrySetSubstrateLoadTrackMotor(bool isRunning)
        {
            return _ioMonitorService.TrySetOutputState(DeviceIoIds.SubstrateLoad.TrackMotorRun, isRunning);
        }

        public Task<bool> WaitSubstrateAtLoadPositionAsync(TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken))
        {
            return _ioMonitorService.WaitForPointStateAsync(DeviceIoNames.SubstrateLoad.SensorIn, true, timeout, cancellationToken);
        }

        public Task<bool> WaitSubstrateLoadHomeCheckedAsync(TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken))
        {
            return _ioMonitorService.WaitForPointStateAsync(DeviceIoNames.SubstrateLoad.HomeChecked, true, timeout, cancellationToken);
        }

        public Task<bool> WaitSubstrateLoadVacuumOkAsync(TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken))
        {
            return _ioMonitorService.WaitForPointStateAsync(DeviceIoNames.SubstrateLoad.VacuumOk, true, timeout, cancellationToken);
        }

        public bool TryExtendClamp()
        {
            return _cylinderService.TryExtend(DeviceCylinderNames.Clamp);
        }

        public bool TryRetractClamp()
        {
            return _cylinderService.TryRetract(DeviceCylinderNames.Clamp);
        }

        public bool TryExtendStopper()
        {
            return _cylinderService.TryExtend(DeviceCylinderNames.Stopper);
        }

        public bool TryRetractStopper()
        {
            return _cylinderService.TryRetract(DeviceCylinderNames.Stopper);
        }

        public bool TryPressDown()
        {
            return _cylinderService.TryExtend(DeviceCylinderNames.Press);
        }

        public bool TryReleasePress()
        {
            return _cylinderService.TryRetract(DeviceCylinderNames.Press);
        }

        public Task<bool> TryExtendClampAndWaitAsync(TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken))
        {
            return _cylinderService.TryExtendAndWaitAsync(DeviceCylinderNames.Clamp, timeout, cancellationToken);
        }

        public Task<bool> TryRetractClampAndWaitAsync(TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken))
        {
            return _cylinderService.TryRetractAndWaitAsync(DeviceCylinderNames.Clamp, timeout, cancellationToken);
        }

        public Task<bool> TryExtendStopperAndWaitAsync(TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken))
        {
            return _cylinderService.TryExtendAndWaitAsync(DeviceCylinderNames.Stopper, timeout, cancellationToken);
        }

        public Task<bool> TryRetractStopperAndWaitAsync(TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken))
        {
            return _cylinderService.TryRetractAndWaitAsync(DeviceCylinderNames.Stopper, timeout, cancellationToken);
        }

        public Task<bool> TryPressDownAndWaitAsync(TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken))
        {
            return _cylinderService.TryExtendAndWaitAsync(DeviceCylinderNames.Press, timeout, cancellationToken);
        }

        public Task<bool> TryReleasePressAndWaitAsync(TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken))
        {
            return _cylinderService.TryRetractAndWaitAsync(DeviceCylinderNames.Press, timeout, cancellationToken);
        }
    }
}
