// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Mobius Forensic Toolkit
// Copyright (C) 2008,2009,2010,2011,2012,2013,2014,2015,2016,2017 Eduardo Aguiar
//
// 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, 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, see <http://www.gnu.org/licenses/>.
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#include <mobius/datetime/date.h>
#include <mobius/datetime/time.h>
#include <mobius/datetime/datetime.h>
#include <mobius/datetime/timedelta.h>
#include <mobius/datetime/conv_iso_string.h>
#include <mobius/datetime/conv_julian.h>
#include <mobius/datetime/conv_nt_timestamp.h>
#include <mobius/datetime/conv_unix_timestamp.h>
#include <mobius/unittest.h>

static void
testcase_date ()
{
  mobius::unittest test ("mobius::datetime::date");

  mobius::datetime::date d1;
  test.ASSERT_EQUAL (d1.get_year (), 0);
  test.ASSERT_EQUAL (d1.get_month (), 0);
  test.ASSERT_EQUAL (d1.get_day (), 0);
  test.ASSERT_FALSE (d1);

  mobius::datetime::date d2 (1980, 11, 23);
  test.ASSERT_EQUAL (d2.get_year (), 1980);
  test.ASSERT_EQUAL (d2.get_month (), 11);
  test.ASSERT_EQUAL (d2.get_day (), 23);
  test.ASSERT_TRUE (d2);

  test.ASSERT_EQUAL (d2 - mobius::datetime::date (1980, 11, 01), 22);
  test.ASSERT_EQUAL (d2 - mobius::datetime::date (1979, 11, 23), 366);
  test.ASSERT_EQUAL (mobius::datetime::date (1980, 11, 1) + 22, d2);
  test.end ();
}

static void
testcase_time ()
{
  mobius::unittest test ("mobius::datetime::time");

  mobius::datetime::time t;
  test.ASSERT_EQUAL (t.to_day_seconds (), 0);
  test.ASSERT_FALSE (t);
  test.end ();
}

static void
testcase_datetime ()
{
  mobius::unittest test ("mobius::datetime::datetime");

  mobius::datetime::datetime dt1;
  test.ASSERT_EQUAL (dt1.get_date ().get_year (), 0);
  test.ASSERT_EQUAL (dt1.get_date ().get_month (), 0);
  test.ASSERT_EQUAL (dt1.get_date ().get_day (), 0);
  test.ASSERT_EQUAL (dt1.get_time ().get_hour (), 0);
  test.ASSERT_EQUAL (dt1.get_time ().get_minute (), 0);
  test.ASSERT_EQUAL (dt1.get_time ().get_second (), 0);
  test.ASSERT_FALSE (dt1);

  mobius::datetime::datetime dt3 = mobius::datetime::datetime_from_nt_timestamp (0);
  test.ASSERT_EQUAL (dt3, mobius::datetime::datetime (1601, 1, 1, 0, 0, 0));
  test.ASSERT_TRUE (dt3);

  mobius::datetime::datetime dt4 = mobius::datetime::datetime_from_unix_timestamp (0);
  test.ASSERT_EQUAL (dt4, mobius::datetime::datetime (1970, 1, 1, 0, 0, 0));
  test.ASSERT_TRUE (dt4);
  test.end ();
}

static void
testcase_timedelta ()
{
  mobius::unittest test ("mobius::datetime::timedelta");

  mobius::datetime::timedelta td1;
  mobius::datetime::datetime dt1 (1970, 1, 1, 0, 0, 0);
  td1.set_years (5);
  td1.set_seconds (7200);

  test.ASSERT_EQUAL (dt1 + td1, mobius::datetime::datetime (1975, 1, 1, 2, 0, 0));
  test.end ();
}

static void
testcase_conv_iso_string ()
{
  mobius::unittest test ("mobius::datetime::conv_iso_string functions");

  mobius::datetime::datetime dt (1980, 11, 23, 10, 15, 45);
  test.ASSERT_EQUAL (date_to_iso_string (dt.get_date ()), "1980-11-23");
  test.ASSERT_EQUAL (time_to_iso_string (dt.get_time ()), "10:15:45");
  test.ASSERT_EQUAL (datetime_to_iso_string (dt), "1980-11-23 10:15:45");
  test.end ();
}

static void
testcase_conv_julian ()
{
  mobius::unittest test ("mobius::datetime::conv_julian functions");
  constexpr mobius::datetime::julian_t EPOCH_NT_DATETIME = 2305813.5;
  constexpr mobius::datetime::julian_t EPOCH_UNIX_DATETIME = 2440587.5;
  constexpr mobius::datetime::julian_t EPOCH_GREGORIAN = 1721425.5;

  mobius::datetime::date d1 = mobius::datetime::date_from_julian (EPOCH_NT_DATETIME);
  test.ASSERT_EQUAL (d1, mobius::datetime::date (1601, 1, 1));

  mobius::datetime::date d2 = mobius::datetime::date_from_julian (EPOCH_UNIX_DATETIME);
  test.ASSERT_EQUAL (d2, mobius::datetime::date (1970, 1, 1));
  test.end ();
}

static void
testcase_conv_nt_timestamp ()
{
  mobius::unittest test ("mobius::datetime::conv_nt_timestamp functions");
  mobius::datetime::datetime d1 = mobius::datetime::datetime_from_nt_timestamp (0);
  test.ASSERT_EQUAL (d1, mobius::datetime::datetime (1601, 1, 1, 0, 0, 0));

  mobius::datetime::datetime d2 = mobius::datetime::datetime_from_nt_timestamp (129319043083437500);
  test.ASSERT_EQUAL (d2, mobius::datetime::datetime (2010, 10, 18, 19, 38, 28));

  test.end ();
}

static void
testcase_conv_unix_timestamp ()
{
  mobius::unittest test ("mobius::datetime::conv_unix_timestamp functions");
  mobius::datetime::datetime d1 = mobius::datetime::datetime_from_unix_timestamp (0);
  test.ASSERT_EQUAL (d1, mobius::datetime::datetime (1970, 1, 1, 0, 0, 0));

  mobius::datetime::datetime d2 = mobius::datetime::datetime_from_unix_timestamp (1448722013);
  test.ASSERT_EQUAL (d2, mobius::datetime::datetime (2015, 11, 28, 14, 46, 53));

  test.end ();
}

void
unittest_datetime ()
{
  testcase_date ();
  testcase_time ();
  testcase_datetime ();
  testcase_timedelta ();
  testcase_conv_iso_string ();
  testcase_conv_julian ();
  testcase_conv_nt_timestamp ();
  testcase_conv_unix_timestamp ();
}
