// Copyright 2018 The Emscripten Authors.  All rights reserved.
// Emscripten is available under two separate licenses, the MIT license and the
// University of Illinois/NCSA Open Source License.  Both these licenses can be
// found in the LICENSE file.

#include <string>
#include <time.h>
#include <cstring>
#include <cstdio>

typedef struct tm TimeStruct;

static std::string formatTM(TimeStruct const& tm) {
  char actualTimeBuffer[256];
  sprintf(actualTimeBuffer, "%04d-%02d-%02dT%02d:%02d:%02d", tm.tm_year + 1900, tm.tm_mon + 1,
    tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
  return actualTimeBuffer;
}

static bool isTimeStructEqual(const TimeStruct& LHS, const TimeStruct& RHS) {
  return LHS.tm_year == RHS.tm_year && LHS.tm_mon == RHS.tm_mon && LHS.tm_mday == RHS.tm_mday &&
         LHS.tm_hour == RHS.tm_hour && LHS.tm_min == RHS.tm_min && LHS.tm_sec == RHS.tm_sec;
}

bool parseAndCompare(const std::string& time, std::string expectedTime) {
  TimeStruct tm;
  memset(&tm, 0, sizeof(TimeStruct));
  static const char* format = "%FT%T%z";
  strptime(time.c_str(), format, &tm);

  std::string actualTime = formatTM(tm);
  printf("%s: %s == %s, %s\n", time.c_str(), actualTime.c_str(), expectedTime.c_str(),
    actualTime == expectedTime ? "true" : "false");

  return actualTime == expectedTime;
}

// Ensure that the %c specifier can roundtrip. Meaning we use the same format
// for strftime and strptime.
bool roundTripCSpecifier() {
  TimeStruct tm;
  time_t t = time(NULL);
  memcpy(&tm, localtime(&t), sizeof(TimeStruct));

  char timeBuffer[256];
  if (strftime(timeBuffer, sizeof(timeBuffer), "%c", &tm) == 0) {
    printf("Failed to format current time\n");
    return false;
  }
  const std::string formattedValue = timeBuffer;

  TimeStruct newTm;
  const char* lastParsed;
  if ((lastParsed = strptime(timeBuffer, "%c", &newTm)) == NULL) {
    printf("Failed to parse time string '%s'\n", timeBuffer);
    return false;
  }

  return isTimeStructEqual(tm, newTm);
}

int main(int argc, char** argv) {
  bool testPassed = parseAndCompare("2018-03-27T19:33:09+0000", "2018-03-27T19:33:09") &&
                    parseAndCompare("2018-03-27T19:33:09-0735", "2018-03-27T19:33:09") &&
                    parseAndCompare("2018-03-27T19:33:09+1043", "2018-03-27T19:33:09") &&
                    parseAndCompare("1900-01-01T00:00:00+0000", "1900-01-01T00:00:00") &&
                    parseAndCompare("2018-12-31T23:59:59+0000", "2018-12-31T23:59:59") &&
                    roundTripCSpecifier();

  if (testPassed) {
    printf("TEST PASSED\n");
  } else {
    printf("TEST FAILED\n");
  }

  return 0;
}
