using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using Maser.Feanor.Model;
using Maser.Feanor.Biz;
using Maser.Feanor.Server;
using System.Net;



namespace Maser.Feanor.Client
{
    public class ClientWorker
    {
        public ClientWorker(Chamber Chamber)
        {
            _Chamber = Chamber;
            ThreadPool.SetMaxThreads(1000, 1000);
            _thread = null;
            _status = ChamberStatus.Init;
                        
            try
            {
                _Server = Servers.GetInstanceByChamber(_Chamber);
            }
            catch (Exception ex)
            {
                string s = "class ClientWorker->Servers.GetInstanceByChamber() (chamber: " + _Chamber.ToString() + ")\n Exception: " + ex.Message;
                throw new Exception(s);
            }
        }

       
        private Thread _thread;

        public ChamberStatus Status { get { return _status; } }
        private ChamberStatus _status;

        private Boolean _isKicking;

        public DateTime LastKick { get { return _lastKick; } }
        private DateTime _lastKick;

        public DateTime LastHTTP { get { return _LastHTTP; } }
        private DateTime _LastHTTP;
       
        private DateTime _LastDBWrite; // Used for detecting idling of server

        Int32 _KickIntervalms = 60000;  // Normal interval for contenttoclient request --> 1 minute
        Int32 interval = 5000;          // Interval for first contenttoclient request --> 5 seconds
                
        private Server.Server _Server;
        public Server.Server Server { get { return _Server; } }

        private Chamber _Chamber;
        public Chamber Chamber { get { return _Chamber; } }

        public bool IsRunning
        {
            get
            {
                return (_thread != null) && _thread.IsAlive && _isKicking;
            }
        }


        public bool Start()
        {
            if (!IsRunning)
            {
                _status = ChamberStatus.Initializing;
                _thread = new Thread(new ThreadStart(ThreadFunction));
                _thread.Start();
                return true;
            }
            return false;
        }


        public bool Stop()
        {
            DateTime OnStop = DateTime.Now;

            _status = ChamberStatus.AbortRequested;

            // De-set _isStarted and wait max 10 seconds for result.
            while ((_isKicking) && (OnStop.AddSeconds(10) > DateTime.Now))
                Thread.Sleep(100);

            if (_isKicking)
            {
                _thread.Abort();
                _isKicking = false;
                return _thread.Join(2000);
            }
            return !_isKicking;
        }


        private void ThreadFunction()
        {
            // Send the time of the Feanor client to the server on startup
            try
            {
                if (!_Server.WriteDatetime(Time.UTC) || !_Server.WriteSensors())
                    _status = ChamberStatus.NoConn;
            }
            catch { _status = ChamberStatus.NoConn; }


            Results resultBiz = new Results();
            _lastKick = DateTime.Now;

            while (_status != ChamberStatus.AbortRequested && ((Thread.CurrentThread.ThreadState & System.Threading.ThreadState.AbortRequested) == 0))
            {
                // Try to read from server every _lastKick milliseconds
                if (DateTime.Now > _lastKick.AddMilliseconds(interval)) // was: _KickIntervalms is het /contenttoclient interval! (nu 1 min!)
                {                    
                    interval = _KickIntervalms;

                    _lastKick = DateTime.Now;
                    if (_Server.Read())
                    {
                        _LastHTTP = DateTime.Now;
                                                                       
                        _status = ChamberStatus.Running;
                        
                        if (_Server.Results.Count > 0)
                        {
                            if(_Server.Chamber.Humidity == true)
                            {
                                resultBiz.Add(_Server.Results); // stuurt de resultaten naar de SQL DB (Results)
                            }
                            else
                            {
                                resultBiz.AddOudeHal(_Server.Results); // stuurt de resultaten naar de SQL DB (Results)
                            }
                            
                            _LastDBWrite = DateTime.Now;
                        }
                        if (DateTime.Now > _LastDBWrite.AddSeconds(_Chamber.Interval * 2))
                            _status = ChamberStatus.Idle;
                    }
                    else
                        _status = ChamberStatus.NoConn;

                }

                // It might be interesting to periodically update the calibration and sensor lists in the server.
                // It might be interesting to periodically update the calibration and sensor lists in the server.
                // _Server.SetSensorsAndCalibrations();

                _isKicking = true;
                Thread.Sleep(250);
            }

            _isKicking = false;
            _status = ChamberStatus.Aborted;
        }




    }
}
