//-------------------------------------------------------------------------------------
// SID Monitor - Utility for Sudden Ionospheric Disturbances Monitoring Stations
// Copyright (C) 2006 - Lionel Loudet
//
// 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 2
// 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, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
//-------------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Text;

namespace SID_monitor
{
    /// <summary>
    /// This class represents date and time in two formats Windows .NET DateTime and Unix Time (seconds since 1st Jan 1970 UTC)
    /// </summary>
    class SIDMonitorDateTime
    {
        #region Constants
        private static readonly UInt64 unixReferenceTime = Convert.ToUInt64(new DateTime(1970, 01, 01, 00, 00, 00, DateTimeKind.Utc).Ticks);
        #endregion

        private UInt64 unixTime;
        private DateTime winTime;

        public SIDMonitorDateTime() // by default, an "Empty" value
        {
            this.unixTime = UInt64.MinValue;
            this.winTime = DateTime.MinValue;
        }

        public SIDMonitorDateTime(UInt64 unixTime)
        {
            this.unixTime = unixTime;
            this.winTime = GetWinTime(unixTime);
        }

        public SIDMonitorDateTime(DateTime winTime)
        {
            this.winTime = winTime;
            this.unixTime = GetUnixTime(winTime);
        }

        public static bool IsNullOrEmpty(SIDMonitorDateTime data)
        {
            return ((data.Equals(null)) || (data.unixTime.Equals(UInt64.MinValue) || data.winTime.Equals(DateTime.MinValue)));
        }

        #region Properties
        /// <summary>
        /// Gets or sets the Unix Time representation of this instance
        /// </summary>
        public UInt64 UnixTime
        {
            get { return this.unixTime; }
            set
            {
                this.unixTime = value;
                this.winTime = GetWinTime(this.unixTime);
            }
        }

        /// <summary>
        /// Gets or sets the DateTime representation of this instance
        /// </summary>
        public DateTime WinTime
        {
            get { return this.winTime; }
            set
            {
                this.winTime = value;
                this.unixTime = GetUnixTime(this.winTime);
            }
        }

        /// <summary>
        /// Gets the date component of this instance
        /// </summary>
        public SIDMonitorDateTime Date
        {
            get
            {
                return new SIDMonitorDateTime(this.winTime.Date);
            }
        }

        /// <summary>
        /// Gets a SIDMonitorDateTime object that is set to the current date and time on this computer, expressed as the Coordinated Universal Time (UTC)
        /// </summary>
        public static SIDMonitorDateTime UtcNow
        {
            get
            {
                return new SIDMonitorDateTime(DateTime.UtcNow);
            }
        }

        #endregion

        #region Public Methods
        /// <summary>
        /// Adds the specified number of days to the value of this instance
        /// </summary>
        public SIDMonitorDateTime AddDays(double value)
        {
            return new SIDMonitorDateTime(this.WinTime.AddDays(value));
        }

        /// <summary>
        /// Adds the specified number of hours to the value of this instance
        /// </summary>
        public SIDMonitorDateTime AddHours(double value)
        {
            return new SIDMonitorDateTime(this.WinTime.AddHours(value));
        }
        #endregion

        #region Private Time Conversion Methods
        /// <summary>
        ///  converts a dateTime to UnixTime
        /// </summary>
        /// <param name="winTime"> the date to convert</param>
        /// <returns>the corresponding unix time</returns>
        private static UInt64 GetUnixTime(DateTime winTime)
        {
            return (UInt64)Math.Round(new TimeSpan(winTime.Ticks - Convert.ToInt64(unixReferenceTime)).TotalSeconds);
        }

        /// <summary>
        ///  converts a UnixTime to a dateTime
        /// </summary>
        /// <param name="winTime"> the date to convert</param>
        /// <returns>the corresponding win time</returns>
        private static DateTime GetWinTime(UInt64 UnixTime)
        {
            return new DateTime(Convert.ToInt64(UnixTime * TimeSpan.TicksPerSecond + unixReferenceTime), DateTimeKind.Utc);
        }
        #endregion
    }
}
