--- Egyptian and Armenian calendar conversions.
-- Ported from "Calendrical Calculations" (4th edition)
-- by Nachum Dershowitz and Edward M. Reingold.
-- Original Lisp code (CALENDRICA 4.0) is Apache 2.0 licensed.
-- @module calendrica-egyptian-armenian
-- @release 0.1 2026-07-19

local M = {}

local basic = require("calendrica-basic")


-- === Epochs ===

-- Fixed date of the Egyptian (Nabonasser) epoch: February 26, 747 BCE (Julian).
local EGYPTIAN_EPOCH = basic.fixed_from_jd(1448638)

-- Fixed date of the Armenian epoch: July 11, 552 CE (Julian).
local ARMENIAN_EPOCH = basic.rd(201443)


-- === Egyptian date constructor ===

-- Egyptian date constructor.
local function egyptian_date(year, month, day)
  return {year, month, day}
end


-- === Egyptian conversion ===

--- Fixed date of Egyptian date `e_date`.
-- @tparam table e_date Egyptian date {year, month, day}.
-- @treturn number Fixed date.
function M.fixed_from_egyptian(e_date)
  local month = basic.standard_month(e_date)
  local day   = basic.standard_day(e_date)
  local year  = basic.standard_year(e_date)
  return EGYPTIAN_EPOCH        -- Days before start of calendar.
    + 365 * (year - 1)         -- Days in prior years.
    + 30 * (month - 1)         -- Days in prior months this year.
    + day - 1                  -- Days so far this month.
end
local fixed_from_egyptian = M.fixed_from_egyptian

-- Alternative fixed date from Egyptian date using sigma.
local function alt_fixed_from_egyptian(e_date) -- luacheck: ignore
  return EGYPTIAN_EPOCH + basic.sigma(
    { e_date, {365, 30, 1} },
    function(e, a) return a * (e - 1) end
  )
end

--- Egyptian date {year, month, day} equivalent to fixed `date`.
-- @tparam number date Fixed date.
-- @treturn table {year, month, day}
function M.egyptian_from_fixed(date)
  local days  = date - EGYPTIAN_EPOCH         -- Elapsed days since epoch.
  local year  = 1 + basic.quotient(days, 365) -- Year since epoch.
  local month = 1 + basic.quotient(days % 365, 30)
  local day   = days
    - 365 * (year - 1)
    - 30 * (month - 1)
    + 1
  return egyptian_date(year, month, day)
end
local egyptian_from_fixed = M.egyptian_from_fixed


-- === Armenian date constructor ===

-- Armenian date constructor.
local function armenian_date(year, month, day) -- luacheck: ignore
  return {year, month, day}
end


-- === Armenian conversion ===

--- Fixed date of Armenian date `a_date`.
-- Same structure as the Egyptian calendar with a different epoch.
-- @tparam table a_date Armenian date {year, month, day}.
-- @treturn number Fixed date.
function M.fixed_from_armenian(a_date)
  local month = basic.standard_month(a_date)
  local day   = basic.standard_day(a_date)
  local year  = basic.standard_year(a_date)
  return ARMENIAN_EPOCH
    + fixed_from_egyptian(egyptian_date(year, month, day))
    - EGYPTIAN_EPOCH
end

--- Armenian date {year, month, day} equivalent to fixed `date`.
-- @tparam number date Fixed date.
-- @treturn table {year, month, day}
function M.armenian_from_fixed(date)
  return egyptian_from_fixed(date + EGYPTIAN_EPOCH - ARMENIAN_EPOCH)
end


return M
