using System;
using System.Threading;
using Microsoft.SPOT.Hardware;

namespace GrFamily.ExternalBoard
{
    /// <summary>
    /// [qäÉÚ±µ½ZT[ÌªèlðÔ·fQ[g
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public delegate void TerminalMeasurementCompleteEventHandler(SensorTerminal sender, SensorTerminal.MeasurementCompleteEventArgs e);

    /// <summary>
    /// [qäðgpµ½ZT[
    /// </summary>
    public class SensorTerminal
    {
        /// <summary>
        /// [qäÉÚ±µ½ZT[ÅÌªèÌCxgnh[
        /// </summary>
        public event TerminalMeasurementCompleteEventHandler MeasurementComplete;

        /// <summary>
        /// AiOüÍs
        /// </summary>
        private readonly AnalogInput _sensor;

        /// <summary>
        /// [qäZT[Ìf[^ðèúIÉªè·é½ßÌ^C}[
        /// </summary>
        private readonly Timer _timer;

        private int _interval = -1;

        /// <summary>
        /// RXgN^[
        /// </summary>
        /// <param name="channel">AiO`l</param>
        public SensorTerminal(Cpu.AnalogChannel channel)
        {
            _sensor = new AnalogInput(channel);

            _timer = new Timer(Measure_Timer, null, Timeout.Infinite, Timeout.Infinite);
        }

        /// <summary>
        /// ZT[f[^ªèÌÔu<br />PÊ : ~b
        /// </summary>
        /// <remarks>³Ì®ÅÈ¢êÍ^C}[ðÀsµÈ¢</remarks>
        public int Interval
        {
            get { return _interval; }
            set { _interval = value; }
        }

        /// <summary>
        /// [qäÉÚ±µ½ZT[©çèúIÉf[^ðæ¾·é
        /// </summary>
        /// <param name="state">¢gp</param>
        private void Measure_Timer(object state)
        {
            if (MeasurementComplete == null)
                return;

            var result = new MeasurementCompleteEventArgs
            {
                RawValue = _sensor.ReadRaw(),
                Value = _sensor.Read()
            };
            MeasurementComplete(this, result);
        }

        /// <summary>
        /// ^C}[ðN®µÄA[qäÉÚ±µ½ZT[©çèúIÉf[^Ìæ¾ðnßé
        /// </summary>
        public void StartTakingMeasurements()
        {
            if (Interval > 0)
            {
                var ts = new TimeSpan(Interval * 10000);
                _timer.Change(ts, ts);
            }
        }

        /// <summary>
        /// [qäÉÚ±µ½ZT[©çèúIÉf[^ðæ¾·é½ßÌ^C}[ðâ~·é
        /// </summary>
        public void StopTakingMeasurements()
        {
            _timer.Change(Timeout.Infinite, Timeout.Infinite);
        }

        /// <summary>
        /// [qäÉÚ±µ½ZT[Ì¶Ìªèlðæ¾·é
        /// </summary>
        /// <returns>0`4095Ìl</returns>
        /// <remarks>GR-PEAChÅÍA/DÏ·Ìªð\Í4096</remarks>
        public int ReadRaw()
        {
            lock (this)
            {
                return _sensor.ReadRaw();
            }
        }

        /// <summary>
        /// [qäÉÚ±µ½ZT[Ìªèlðæ¾·é
        /// </summary>
        /// <returns>0`1.0Ìl</returns>
        public double Read()
        {
            lock (this)
            {
                return _sensor.Read();
            }
        }


        /// <summary>
        /// f[^æ¾ÌCxgnh[Én³êéZT[f[^i[qäÉÚ±µ½ZT[j
        /// </summary>
        public class MeasurementCompleteEventArgs
        {
            /// <summary>0`4095Ìl</summary>
            public int RawValue;
            /// <summary>0`1.0Ìl</summary>
            public double Value;
        }
    }
}
