--- Akan day-name calendar.
-- 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-akan
-- @release 0.1 2026-07-19

local M = {}

local basic = require("calendrica-basic")


-- === Epoch ===

-- RD date of Akan day-name epoch.
local AKAN_DAY_NAME_EPOCH = basic.rd(37)


-- === Name constructor and accessors ===

local function akan_name(prefix, stem) return {prefix, stem} end
local function akan_prefix(name) return name[1] end
local function akan_stem(name)   return name[2] end

-- n-th name of the 42-day Akan cycle.
local function akan_day_name(n)
  return akan_name(basic.amod(n, 6), basic.amod(n, 7))
end

-- Days from a_name1 to the next occurrence of a_name2.
local function akan_name_difference(a_name1, a_name2)
  local prefix1 = akan_prefix(a_name1)
  local prefix2 = akan_prefix(a_name2)
  local stem1   = akan_stem(a_name1)
  local stem2   = akan_stem(a_name2)
  local prefix_difference = prefix2 - prefix1
  local stem_difference   = stem2 - stem1
  return basic.amod(
    prefix_difference + 36 * (stem_difference - prefix_difference),
    42
  )
end

--- Akan day name for fixed `date`.
-- @tparam number date Fixed date.
-- @treturn table {prefix, stem}
function M.akan_name_from_fixed(date)
  return akan_day_name(date - AKAN_DAY_NAME_EPOCH)
end
local akan_name_from_fixed = M.akan_name_from_fixed

-- Latest date on or before date with the given Akan name.
local function akan_day_name_on_or_before(name, date)
  return basic.mod3(
    akan_name_difference(akan_name_from_fixed(0), name),
    date,
    date - 42
  )
end


-- === Exports ===

--- The n-th name of the 42-day Akan cycle.
-- @function akan_day_name
-- @tparam number n Position in cycle.
-- @treturn table {prefix, stem}
M.akan_day_name = akan_day_name

--- Days from `a_name1` to the next occurrence of `a_name2` in the Akan cycle.
-- @function akan_name_difference
-- @tparam table a_name1 Akan name {prefix, stem}.
-- @tparam table a_name2 Akan name {prefix, stem}.
-- @treturn number Count (1..42).
M.akan_name_difference = akan_name_difference

--- Latest fixed date on or before `date` with the given Akan `name`.
-- @function akan_day_name_on_or_before
-- @tparam table  name Akan name {prefix, stem}.
-- @tparam number date Fixed date.
-- @treturn number Fixed date.
M.akan_day_name_on_or_before = akan_day_name_on_or_before


return M
