using Newtonsoft.Json;
using System;

namespace Cryville.Crtr {
	[JsonConverter(typeof(BeatTimeConverter))]
	public struct BeatTime : IComparable<BeatTime>, IEquatable<BeatTime> {
		public BeatTime(int _b, int _n, int _d) {
			b = _b;
			n = _n;
			d = _d;
		}
		public BeatTime(int _n, int _d) {
			b = _n / _d;
			n = _n % _d;
			d = _d;
		}

		[JsonIgnore]
		public int b;
		
		[JsonIgnore]
		public int n;
		
		[JsonIgnore]
		public int d;

		[JsonIgnore]
		public double Decimal { get { return b + (double)n / d; } }

		public int CompareTo(BeatTime other) {
			var c = b.CompareTo(other.b);
			if (c != 0) return c;
			return ((double)n / d).CompareTo((double)other.n / other.d);
		}

		public override bool Equals(object obj) {
			if (!(obj is BeatTime)) return false;
			return Equals((BeatTime)obj);
		}

		public bool Equals(BeatTime other) {
			return b.Equals(other.b) && ((double)n / d).Equals((double)other.n / other.d);
		}

		public override int GetHashCode() {
			return Decimal.GetHashCode();
		}

		public static bool operator ==(BeatTime left, BeatTime right) {
			return left.Equals(right);
		}

		public static bool operator !=(BeatTime left, BeatTime right) {
			return !left.Equals(right);
		}
	}
	public class BeatTimeConverter : JsonConverter {
		public override bool CanConvert(Type objectType) {
			return objectType == typeof(int[]);
		}

		public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
			int b = (int)reader.ReadAsInt32();
			int n = (int)reader.ReadAsInt32();
			int d = (int)reader.ReadAsInt32();
			reader.Read();
			return new BeatTime(b, n, d);
		}

		public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
			BeatTime obj = (BeatTime)value;
			writer.WriteStartArray();
			writer.WriteValue(obj.b);
			writer.WriteValue(obj.n);
			writer.WriteValue(obj.d);
			writer.WriteEndArray();
		}
	}
}
