// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.


#pragma once

#include <limits>
#include <string>

#include "common/logging.h"
#include "common/status.h"
#include "udf/udf.h"

namespace impala {

namespace datetime_parse_util {
struct DateTimeFormatContext;
}

/// Represents a DATE value.
/// - The minimum and maximum dates are 0001-01-01 and 9999-12-31. Valid dates must fall
///   in this range.
/// - Internally represents DATE values as number of days since 1970-01-01.
/// - This representation was chosen to be the same (bit-by-bit) as Parquet's date type.
///   (https://github.com/apache/parquet-format/blob/master/LogicalTypes.md#date)
/// - Proleptic Gregorian calendar is used to calculate the number of days since epoch,
///   which can lead to different representation of historical dates compared to Hive.
///   (https://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar).
/// - Supports construction from year-month-day triplets. In this case, CCTZ is used to
///   check the validity of date.
/// - A DateValue instance will be invalid in the following cases:
///     - If created using the default constructor.
///     - If constructed from out-of-range or invalid year-month-day values.
///     - If parsed from a date string that is not valid or represents an out-of-range
///       date.
/// - Note, that boost::gregorian::date could not be used for representation/validation
///   due to its limited range.
class DateValue {
 public:
  static const DateValue MIN_DATE;
  static const DateValue MAX_DATE;

  /// Default constructor creates an invalid DateValue instance.
  DateValue() : days_since_epoch_(INVALID_DAYS_SINCE_EPOCH) {
    DCHECK(!IsValid());
  }

  explicit DateValue(int64_t days_since_epoch)
      : days_since_epoch_(INVALID_DAYS_SINCE_EPOCH) {
    DCHECK(!IsValid());
    if (LIKELY(days_since_epoch >= MIN_DAYS_SINCE_EPOCH
        && days_since_epoch <= MAX_DAYS_SINCE_EPOCH)) {
      days_since_epoch_ = static_cast<int32_t>(days_since_epoch);
      DCHECK(IsValid());
    }
  }

  DateValue(int64_t year, int64_t month, int64_t day);

  /// Creates a DateValue instance from the ISO 8601 week-based date values:
  /// 'year' is expected to be in the [1, 9999] range.
  /// 'week_of_year' is expected to be in the [1, 53] range.
  /// 'day_of_week' is expected to be in the [1, 7] range.
  /// If any of the parameters is out of range or 'year' has less than 'week_of_year'
  /// ISO 8601 weeks, returns an invalid DateValue instance.
  static DateValue CreateFromIso8601WeekBasedDateVals(int week_numbering_year,
      int week_of_year, int day_of_week);

  bool IsValid() const {
    return days_since_epoch_ != INVALID_DAYS_SINCE_EPOCH;
  }

  /// If this DateValue instance is valid, return the string representation formatted as
  /// 'yyyy-MM-dd'.
  /// Otherwise, return empty string.
  std::string ToString() const;

  /// If this DateValue instance is valid, convert it to year-month-day and return true.
  /// Result is placed in 'year', 'month', 'day'.
  /// Otherwise, return false.
  bool ToYearMonthDay(int* year, int* month, int* day) const WARN_UNUSED_RESULT;

  /// If this DateValue instance is valid, convert it to year and return true. Result is
  /// placed in 'year'.
  /// Otherwise, return false.
  bool ToYear(int* year) const WARN_UNUSED_RESULT;

  /// If DateValue instance is valid, returns day-of-week in [0, 6] range; 0 = Monday and
  /// 6 = Sunday.
  /// Otherwise, return -1.
  int WeekDay() const;

  /// If DateValue instance is valid, returns day-of-year in [1, 366] range.
  /// Otherwise, return -1.
  int DayOfYear() const;

  /// Returns the ISO 8601 week corresponding to this date.
  /// If this DateValue instance is invalid, the return value is -1; otherwise the return
  /// value is in the [1, 53] range.
  /// ISO 8601 weeks start with Monday. Each ISO 8601 week's year is the Gregorian year in
  /// which the Thursday falls.
  int Iso8601WeekOfYear() const;

  /// Returns the year that the current ISO 8601 week belongs to.
  /// If this DateValue instance is invalid, the return value is -1; otherwise the return
  /// value is in the [current_year - 1, current_year + 1] range, which always falls into
  /// the [1, 9999] range.
  /// ISO 8601 weeks start with Monday. Each ISO 8601 week's year is the Gregorian year in
  /// which the Thursday falls.
  int Iso8601WeekNumberingYear() const;

  /// If this DateValue instance valid, add 'days' days to it and return the result.
  /// Otherwise, return an invalid DateValue instance.
  DateValue AddDays(int64_t days) const;

  /// If this DateValue instance valid, add 'months' months to it and return the result.
  /// Otherwise, return an invalid DateValue instance.
  /// If 'keep_last_day' is set and this DateValue is the last day of a month, the
  /// returned DateValue will fall on the last day of the target month too.
  DateValue AddMonths(int64_t months, bool keep_last_day) const;

  /// If this DateValue instance valid, add 'years' years to it and return the result.
  /// Otherwise, return an invalid DateValue instance.
  DateValue AddYears(int64_t years) const;

  /// If this DateValue instance is valid, convert it to the number of days since epoch
  /// and return true. Result is placed in 'days'.
  /// Otherwise, return false.
  bool ToDaysSinceEpoch(int32_t* days) const WARN_UNUSED_RESULT;

  /// If this DateValue instance is valid, return DateValue corresponding to the last day
  /// of the current month.
  /// Otherwise, return an invalid DateValue instance.
  DateValue LastDay() const;

  /// If this DateValue and 'other' are both valid, set 'months_between' to the number of
  /// months between dates and return true. Otherwise return false.
  /// If this is later than 'other', then the result is positive. If this is earlier than
  /// 'other', then the result is negative. If this and 'other' are either the same days
  /// of the month or both last days of months, then the result is always an integer.
  /// Otherwise calculate the fractional portion of the result based on a 31-day month.
  bool MonthsBetween(const DateValue& other, double* months_between) const;

  /// Returns a DateVal representation in the output variable.
  /// Returns null if the DateValue instance doesn't have a valid date.
  impala_udf::DateVal ToDateVal() const {
    if (!IsValid()) return impala_udf::DateVal::null();
    return impala_udf::DateVal(days_since_epoch_);
  }

  /// Returns the underlying storage. There is only one representation for any DateValue
  /// (including the invalid DateValue) and the storage is directly comparable.
  int32_t Value() const { return days_since_epoch_; }

  /// Returns a DateValue converted from a DateVal. The caller must ensure the DateVal
  /// does not represent a NULL.
  static DateValue FromDateVal(const impala_udf::DateVal& udf_value) {
    DCHECK(!udf_value.is_null);
    return DateValue(udf_value.val);
  }

  /// Constructors that parse from a date string. See DateParser for details about the
  /// date format.
  static DateValue ParseSimpleDateFormat(const char* str, int len, bool accept_time_toks);
  static DateValue ParseSimpleDateFormat(const std::string& str, bool accept_time_toks);
  static DateValue ParseSimpleDateFormat(const char* str, int len,
      const datetime_parse_util::DateTimeFormatContext& dt_ctx);
  static DateValue ParseIsoSqlFormat(const char* str, int len,
      const datetime_parse_util::DateTimeFormatContext& dt_ctx);

  /// Format the date using the given 'dt_ctx' format context. If *this is invalid
  /// returns an empty string.
  std::string Format(const datetime_parse_util::DateTimeFormatContext& dt_ctx) const;

  bool operator==(const DateValue& other) const {
    return days_since_epoch_ == other.days_since_epoch_;
  }
  bool operator!=(const DateValue& other) const { return !(*this == other); }

  bool operator<(const DateValue& other) const {
    return days_since_epoch_ < other.days_since_epoch_;
  }
  bool operator>(const DateValue& other) const { return other < *this; }
  bool operator<=(const DateValue& other) const { return !(*this > other); }
  bool operator>=(const DateValue& other) const { return !(*this < other); }

 private:
  /// Number of days since 1970.01.01.
  int32_t days_since_epoch_;

  static const int32_t MIN_DAYS_SINCE_EPOCH;
  static const int32_t MAX_DAYS_SINCE_EPOCH;
  static const int32_t INVALID_DAYS_SINCE_EPOCH = std::numeric_limits<int32_t>::min();
};

std::ostream& operator<<(std::ostream& os, const DateValue& date_value);

}
