using Modbus.Device;
using System;
using System.Net.Sockets;
using Optional;

namespace BoFilTest.Domain.Modules
{
    class MKSOverModbusGasFlowMeasure : IGasFlowMeasure
    {
        private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
        private static ushort flowRegisterLength = 2;
        private static ushort flowRegisterAddress = 0x4000;
        private static double squareCentimetersPerLiter = 1000.0;
        private static double minutesPerHour = 60.0;

        private readonly TcpClient client;
        private readonly ModbusIpMaster master;

        public int CalibrationCurveIndex { get => 0; set => throw new NotImplementedException(); }

        public Option<LiterPerHour> ReadValue()
        {
            ushort[] inputs = master.ReadInputRegisters(flowRegisterAddress, flowRegisterLength);
            float value = ModbusUtilities.DecodeFloat(inputs);
            // BOF-34: the gas flow measure reports cm²/min, which we convert to liter per hour
            return Option.Some(new LiterPerHour(value / squareCentimetersPerLiter * minutesPerHour));
        }

        public MKSOverModbusGasFlowMeasure(string host)
        {
            const int port = 502;

            logger.Info("Connecting gas flow measure to {0}:{1}", host, port);
            this.client = new TcpClient(host, port);
            this.master = ModbusIpMaster.CreateIp(client);
            this.client.ReceiveTimeout = 1000;
            this.client.SendTimeout = 1000;
        }

        public void Cleanup()
        {
            // clean up
            this.client.Close();
            logger.Info("Disconnected gas flow measure.");
        }

        public void ResetIntegral()
        {
            // Not implemented for this device
        }

        public float? ReadIntegral()
        {
            return 0.0f;
        }
    }
}
