#ifndef TIME_ZONE_COMMON_H
#define TIME_ZONE_COMMON_H
/* Copyright (c) 2004, 2024, Oracle and/or its affiliates.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License, version 2.0,
   as published by the Free Software Foundation.

   This program is designed to work with certain software (including
   but not limited to OpenSSL) that is licensed under separate terms,
   as designated in a particular file or component or in included license
   documentation.  The authors of MySQL hereby grant you an additional
   permission to link the program and your derivative works with the
   separately licensed software that they have either included with
   the program or referenced in the documentation.

   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, version 2.0, for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */

#include "my_alloc.h"   // MEM_ROOT
#include "my_time_t.h"  // my_time_t
/**
  @file
  Contains common functionality shared between mysqld and
  mysql_tz_info_to_sql.
*/

/*
  Now we don't use abbreviations in server but we will do this in future.
*/
#if !defined(NDEBUG)
/* Let use abbreviations for debug purposes */
#undef ABBR_ARE_USED
#define ABBR_ARE_USED
#endif /* !defined(NDEBUG) */

/* Structure describing local time type (e.g. Moscow summer time (MSD)) */
typedef struct ttinfo {
  long tt_gmtoff;     // Offset from UTC in seconds
  unsigned tt_isdst;  // Is daylight saving time or not. Used to set tm_isdst
#ifdef ABBR_ARE_USED
  unsigned tt_abbrind;  // Index of start of abbreviation for this time type.
#endif
  /*
    We don't use tt_ttisstd and tt_ttisgmt members of original elsie-code
    struct since we don't support POSIX-style TZ descriptions in variables.
  */
} TRAN_TYPE_INFO;

/* Structure describing leap-second corrections. */
typedef struct lsinfo {
  my_time_t ls_trans;  // Transition time
  long ls_corr;        // Correction to apply
} LS_INFO;

/*
  Structure with information describing ranges of my_time_t shifted to local
  time (my_time_t + offset). Used for local MYSQL_TIME -> my_time_t conversion.
  See comments for TIME_to_gmt_sec() for more info.
*/
typedef struct revtinfo {
  long rt_offset;    // Offset of local time from UTC in seconds
  unsigned rt_type;  // Type of period 0 - Normal period. 1 - Spring time-gap
} REVT_INFO;

#ifdef TZNAME_MAX
#define MY_TZNAME_MAX TZNAME_MAX
#endif
#ifndef TZNAME_MAX
#define MY_TZNAME_MAX 255
#endif

/*
  Structure which fully describes time zone which is
  described in our db or in zoneinfo files.
*/
struct TIME_ZONE_INFO {
  unsigned leapcnt;  // Number of leap-second corrections
  unsigned timecnt;  // Number of transitions between time types
  unsigned typecnt;  // Number of local time types
  size_t charcnt;    // Number of characters used for abbreviations
  unsigned
      revcnt;  // Number of transition descr. for TIME->my_time_t conversion
  /* The following are dynamical arrays are allocated in MEM_ROOT */
  my_time_t *ats;        // Times of transitions between time types
  uchar *types;          // Local time types for transitions
  TRAN_TYPE_INFO *ttis;  // Local time types descriptions
#ifdef ABBR_ARE_USED
  /* Storage for local time types abbreviations. They are stored as ASCIIZ */
  char *chars;
#endif
  /*
    Leap seconds corrections descriptions, this array is shared by
    all time zones who use leap seconds.
  */
  LS_INFO *lsis;
  /*
    Starting points and descriptions of shifted my_time_t (my_time_t + offset)
    ranges on which shifted my_time_t -> my_time_t mapping is linear or
    undefined. Used for tm -> my_time_t conversion.
  */
  my_time_t *revts;
  REVT_INFO *revtis;
  /*
    Time type which is used for times smaller than first transition or if
    there are no transitions at all.
  */
  TRAN_TYPE_INFO *fallback_tti;
};

/*
  Finish preparation of time zone description for use in TIME_to_gmt_sec()
  and gmt_sec_to_TIME() functions.

  SYNOPSIS
    prepare_tz_info()
      sp - pointer to time zone description
      storage - pointer to MEM_ROOT where arrays for map allocated

  DESCRIPTION
    First task of this function is to find fallback time type which will
    be used if there are no transitions or we have moment in time before
    any transitions.
    Second task is to build "shifted my_time_t" -> my_time_t map used in
    MYSQL_TIME -> my_time_t conversion.
    Note: See description of TIME_to_gmt_sec() function first.
    In order to perform MYSQL_TIME -> my_time_t conversion we need to build
  table which defines "shifted by tz offset and leap seconds my_time_t" ->
    my_time_t function which is almost the same (except ranges of ambiguity)
    as reverse function to piecewise linear function used for my_time_t ->
    "shifted my_time_t" conversion and which is also specified as table in
    zoneinfo file or in our db (It is specified as start of time type ranges
    and time type offsets). So basic idea is very simple - let us iterate
    through my_time_t space from one point of discontinuity of my_time_t ->
    "shifted my_time_t" function to another and build our approximation of
    reverse function. (Actually we iterate through ranges on which
    my_time_t -> "shifted my_time_t" is linear function).

  RETURN VALUES
    0	Ok
    1	Error
*/
bool prepare_tz_info(TIME_ZONE_INFO *sp, MEM_ROOT *storage);

#endif  // TIME_ZONE_COMMON_H
