using System;
using Microsoft.SPOT;

namespace CPF
{
    public class NMEA_Decimal
    {
        private bool    _valid;
        private bool    _updated;
        private long    _lastCommitTime;
        private int     _val;
        private int     _newval;

        public void Commit() 
        {
            _val = _newval;
            _lastCommitTime = Utils.MillisecondsSinceLastReboot();
            _valid = _updated = true;
        }

        public void Set(ByteString s) 
        {
            _newval = Conversions.ParseDecimal(s);
        }

        public bool IsValid() 
        { 
            return _valid; 
        }

        public bool IsUpdated() 
        { 
            return _updated; 
        }

        public long Age() 
        { 
            return _valid ? Utils.MillisecondsSinceLastReboot() - _lastCommitTime : Conversions.MAX_SIGNED; 
        }
        
        public int Value() 
        { 
            _updated = false; 
            return _val; 
        }

        public NMEA_Decimal()
        {
            _valid = false;
            _updated = false;
            _val = 0;
            _lastCommitTime = 0;
        }
    }

    public class NMEA_Speed : NMEA_Decimal
    {
        private const double    _MPH_PER_KNOT       = 1.15077945;
        private const double    _MPS_PER_KNOT       = 0.51444444;
        private const double    _KMPH_PER_KNOT      = 1.852;

        double Knots() { return Value() / 100.0; }
        double MPH() { return _MPH_PER_KNOT * Value() / 100.0; }
        double MPS() { return _MPS_PER_KNOT * Value() / 100.0; }
        double KMPH() { return _KMPH_PER_KNOT * Value() / 100.0; }
    }

    public class NMEA_Course : NMEA_Decimal
    {
        double Degrees() { return Value() / 100.0; }
    }

    public class NMEA_Altitude : NMEA_Decimal
    {
        private const double _MILES_PER_METER = 0.00062137112;
        private const double _KM_PER_METER = 0.001;
        private const double _FEET_PER_METER = 3.2808399;

        double Meters() { return Value() / 100.0; }
        double Miles() { return _MILES_PER_METER * Value() / 100.0; }
        double kilometers() { return _KM_PER_METER * Value() / 100.0; }
        double Feet() { return _FEET_PER_METER * Value() / 100.0; }
    }
}
