// Created with MonoDevelop
//
//    Copyright (C) 2023 Hiperscan GmbH Dresden, Germany
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

using System;

namespace Hiperscan.SGS.Benchtop.TemperatureControl
{
    public class CapsuleTemperature
    {
        public CapsuleTemperature(int history_count = 10, int interval_sec = 300)
        {
            this.ActualTemperature = new Temperature(history_count, interval_sec);
        }

        public CapsuleTemperature Clone()
        {
            return new CapsuleTemperature()
            {
                SetTemperature = this.SetTemperature,
                SetHysteresisTemperature = this.SetHysteresisTemperature,
                ActualTemperature = this.ActualTemperature.Clone(),
                Mode = this.Mode,
                FanOn = this.FanOn,
                HeaterOn = this.HeaterOn,
                GradientLimit = this.GradientLimit,
                MinStableTemperature = this.MinStableTemperature,
            };
        }

        public int GradientLimit { get; set; } = 20;
        public int MinStableTemperature { get; set; } = 30;

        public double SetTemperature { get; set; } = double.NaN;
        public double SetHysteresisTemperature { get; set; } = double.NaN;
        public CapsuleHeaterMode Mode { get; set; } = CapsuleHeaterMode.Stable;
        public bool HeaterOn { get; set; } = false;
        public bool FanOn { get; set; } = false;
       //public HeaterState HeaterState { get; set; } = HeaterState.Off;

        public Temperature ActualTemperature { get; protected set; }

        public virtual void ConvertToMode(byte data)
        {
            this.HeaterOn = (data & 0x02) == 1;
            this.FanOn = (data & 0x01) == 1;
            this.Mode = (CapsuleHeaterMode)((data >> 6) & 0x03);
        }

        public override string ToString()
        {
            String data = "Capsule Temperature Data:\n";
            data += String.Format("\tSet temperature   : {0:F2}°C\n", this.SetTemperature);
            data += String.Format("\tSet hysteresis    : {0:F2}°C\n", this.SetHysteresisTemperature);
            data += String.Format("\tActual temperature: {0}\n", this.ActualTemperature);
            //data += String.Format("\tHeater state      : {0}\n", this.HeaterState);
            data += String.Format("\tHeater mode       : {0}\n", this.Mode);
            data += String.Format("\tHeater on         : {0}\n", this.HeaterOn);
            data += String.Format("\tFan on            : {0}\n", this.FanOn);

            return data;
        }

        public bool IsStable
        {
            get
            {
                //TODO upper and lower gradient should be nice
                double gradient = Math.Abs(this.ActualTemperature.GradientDegreePerHour);
                return gradient < this.GradientLimit &&
                       this.ActualTemperature.LastTemperature > this.MinStableTemperature;
            }
        }

        public virtual byte ModeAsBitMask
        {
            get
            {
                byte complex_mode = (byte)(((byte)this.Mode) << 6);

                if (this.HeaterOn)
                    complex_mode += 2;

                if (this.FanOn)
                    complex_mode += 1;

                return complex_mode;
            } 
        }
    }
}
