using System;

namespace Jovian.Calendar {
    /// <summary>
    /// Represents a point in world-calendar time. Display-friendly.
    /// All fields are 0-indexed internally; display properties are 1-indexed where expected.
    /// </summary>
    [Serializable]
    public struct WorldDateTime : IEquatable<WorldDateTime>, IComparable<WorldDateTime> {
        public int year;
        public int month; // 0-indexed
        public int day; // 0-indexed
        public int hour;
        public int minute;

        /// <summary>1-indexed day for display.</summary>
        public int DisplayDay => day + 1;

        /// <summary>1-indexed month for display.</summary>
        public int DisplayMonth => month + 1;

        /// <summary>Returns "HH:MM" style time string.</summary>
        public string TimeString => $"{hour:D2}:{minute:D2}";

        /// <summary>Returns "Day/Month/Year" display string (1-indexed).</summary>
        public string DateString => $"{DisplayDay}/{DisplayMonth}/{year}";

        /// <summary>Returns full "Day/Month/Year HH:MM".</summary>
        public string FullString => $"{DateString} {TimeString}";

        public bool Equals(WorldDateTime other) {
            return year == other.year && month == other.month && day == other.day
                && hour == other.hour && minute == other.minute;
        }

        public int CompareTo(WorldDateTime other) {
            var c = year.CompareTo(other.year);
            if(c != 0) {
                return c;
            }
            c = month.CompareTo(other.month);
            if(c != 0) {
                return c;
            }
            c = day.CompareTo(other.day);
            if(c != 0) {
                return c;
            }
            c = hour.CompareTo(other.hour);
            if(c != 0) {
                return c;
            }
            return minute.CompareTo(other.minute);
        }

        public override bool Equals(object obj) {
            return obj is WorldDateTime other && Equals(other);
        }

        public override int GetHashCode() {
            return HashCode.Combine(year, month, day, hour, minute);
        }

        public override string ToString() {
            return FullString;
        }

        public static bool operator ==(WorldDateTime a, WorldDateTime b) {
            return a.Equals(b);
        }

        public static bool operator !=(WorldDateTime a, WorldDateTime b) {
            return !a.Equals(b);
        }

        public static bool operator <(WorldDateTime a, WorldDateTime b) {
            return a.CompareTo(b) < 0;
        }

        public static bool operator >(WorldDateTime a, WorldDateTime b) {
            return a.CompareTo(b) > 0;
        }

        public static bool operator <=(WorldDateTime a, WorldDateTime b) {
            return a.CompareTo(b) <= 0;
        }

        public static bool operator >=(WorldDateTime a, WorldDateTime b) {
            return a.CompareTo(b) >= 0;
        }
    }
}
