/**
 * @file
 *
 * @date Created  on Oct 13, 2025
 * @author Attila Kovacs
 */

#include <iostream>

#include "TestUtil.hpp"



int main() {
  TestUtil test = TestUtil("Interval");

  int n = 0;

  Interval x(NAN);
  if(!test.check("is_valid(NAN)", !x.is_valid())) n++;
  if(!test.check("isnan(NAN)", isnan(x.seconds()))) n++;
  if(!test.check("to_timescale(NAN)", !x.to_timescale(NOVAS_TT).is_valid())) n++;
  if(!test.check("NAN.operator*(ScalarVelocity&)", !(x * ScalarVelocity::stationary()).is_valid())) n++;
  if(!test.check("NAN.operator*(Velocity&)", !(x * Velocity::stationary()).is_valid())) n++;
  if(!test.check("NAN.operator+()", !(x + Interval::zero()).is_valid())) n++;
  if(!test.check("NAN.operator-()", !(x - Interval::zero()).is_valid())) n++;

  if(!test.check("is_valid(zero)", Interval::zero().is_valid())) n++;
  if(!test.equals("zero()", Interval::zero().minutes(), 0.0)) n++;

  if(!test.check("is_valid(timescale -1)", !Interval(1.0, (enum novas_timescale) -1).is_valid())) n++;

  Interval a(1.0 * Unit::min);
  if(!test.check("is_valid(1 min)", a.is_valid())) n++;
  if(!test.equals("hours()", a.hours(), 1.0 / 60.0, 1e-16)) n++;
  if(!test.equals("minutes)", a.minutes(), 1.0)) n++;
  if(!test.equals("seconds()", a.seconds(), 60.0, 1e-14)) n++;
  if(!test.equals("milliseconds()", a.milliseconds(), 60000.0, 1e-11)) n++;
  if(!test.equals("arcsec()", a.days(), Unit::min / Unit::day, 1e-18)) n++;
  if(!test.equals("weeks()", a.weeks(), Unit::min / Unit::week, 1e-19)) n++;
  if(!test.equals("years()", a.years(), Unit::min / Unit::yr, 1e-10)) n++;
  if(!test.equals("julian_years()", a.julian_years(), Unit::min / Unit::julian_year, 1e-22)) n++;
  if(!test.equals("julian_centuries()", a.julian_centuries(), Unit::min / Unit::julian_century, 1e-23)) n++;
  if(!test.equals("timescale()", (long) a.timescale(), (long) NOVAS_TT)) n++;
  if(!test.equals("SI_unit()", a.SI_unit(), "s")) n++;
  if(!test.equals("SI_value()", a.SI_value(), a.seconds(), 0.0)) n++;
  if(!test.equals("operator - (tt)", (a - a).seconds(), 0.0, 1e-16)) n++;
  if(!test.check("operator+(NAN)", !(a + x).is_valid())) n++;
  if(!test.check("operator-(NAN)", !(a - x).is_valid())) n++;
  if(!test.check("to_timescale(invalid)", !x.to_timescale((enum novas_timescale) -1).is_valid())) n++;

  if(!test.equals("inv()", a.inv().minutes(), -1.0)) n++;

  if(!test.equals("operator * (ScalarVelocity)", (a * ScalarVelocity(1.0)).m(), 60.0, 1e-12)) n++;
  if(!test.equals("operator * (Velocity)", (a * Velocity(1.0, -1.0, 0.0)).distance().m(), sqrt(2.0) * 60.0)) n++;

  Interval b(59.0 * Unit::sec);
  if(!test.check("operator ==", a == a)) n++;
  if(!test.check("operator !=", a != b)) n++;

  if(!test.equals("operator +", (a + b).seconds(), 119.0, 1e-12)) n++;
  if(!test.equals("operator -", (a - b).seconds(), 1.0, 1e-12)) n++;

  Interval c(1000.0 * Unit::sec, NOVAS_TCG);
  if(!test.equals("tcg:seconds()", c.seconds(), 1000.0)) n++;
  if(!test.equals("tcg:to_tt:seconds()", c.to_timescale(NOVAS_TT).seconds() * (1.0 + Constant::L_G), 1000.0, 1e-16)) n++;
  if(!test.equals("operator - (tcg)", (c - c).seconds(), 0.0, 1e-16)) n++;

  Interval d(1000.0 * Unit::sec, NOVAS_TCB);
  if(!test.equals("tcb:seconds()", d.seconds(), 1000.0)) n++;
  if(!test.equals("tcb:to_tt:seconds()", d.to_timescale(NOVAS_TT).seconds() * (1.0 + Constant::L_B), 1000.0, 1e-16)) n++;
  if(!test.equals("operator - (tcb)", (d - d).seconds(), 0.0, 1e-16)) n++;

  if(!test.differs("operator - (tcb / tcg)", (d - c).seconds(), 0.0, 1e-15)) n++;

  if(!test.equals("to_string(10 ps)", Interval(10.0 * Unit::ps).to_string(), "10.000 ps")) n++;
  if(!test.equals("to_string(10 ns)", Interval(10.0 * Unit::ns).to_string(), "10.000 ns")) n++;
  if(!test.equals("to_string(10 us)", Interval(10.0 * Unit::us).to_string(), "10.000 us")) n++;
  if(!test.equals("to_string(10 ms)", Interval(10.0 * Unit::ms).to_string(), "10.000 ms")) n++;
  if(!test.equals("to_string(10 s)", Interval(10.0 * Unit::s).to_string(), "10.000 s")) n++;
  if(!test.equals("to_string(10 min)", Interval(10.0 * Unit::min).to_string(), "600.000 s")) n++;
  if(!test.equals("to_string(10 h)", Interval(10.0 * Unit::hour).to_string(), "10.000 h")) n++;
  if(!test.equals("to_string(10 d)", Interval(10.0 * Unit::day).to_string(), "10.000 d")) n++;
  if(!test.equals("to_string(10 yr)", Interval(10.0 * Unit::yr).to_string(), "10.000 yr")) n++;

  Interval dt(-Constant::pi * Unit::s);
  if(!test.equals("to_string(decimals=0)", dt.to_string(-1), dt.to_string(0))) n++;
  if(!test.equals("to_string(decimals=17)", dt.to_string(17), dt.to_string(16))) n++;

  std::cout << "Interval.cpp: " << (n > 0 ? "FAILED" : "OK") << "\n";
  return n;
}
