-- you can use your own month names and so on; even if you change
-- the length of the year the code will adapt

local imperial = {
	days = {
		'Day of the Frozen River'; 'Day of Fell Shadow';
		'Day of Peaceful Splendor'; 'Day of Somber Reflection'; 
		'Day of Wrathful Visitation'; 'Day of Wistful Remembrance';
		'Day of the Warm Hearth'; 'Day of Joyous Worship';
		'Day of the Fond Farewell';
	};
	weeks = {
		"Merchant's Week"; "Chandler's Week"; "Miller's Week";
		"Bard's Week"; "Cobbler's Week";
	};
	moons = {
		'Splendormoon';
		'Embermoon';
		'Saddlemoon';
		'Candlemoon';
		'Cindermoon';
		'Diremoon';
		'Chancelmoon';
		'Starmoon';
		'Harvestmoon';
	};
}

local magisterial = {
	days = {
		'Shortmarket'; 'Fellwind'; 'Brightmorn'; 'Wandflame';
		'Goldmorrow'; 'Slaketide'; 'Longmarket'; 'Furlblossom';
	};
	weeks = {
		'Slavemarket';
		'Wandmarket';
		'Thriftmarket';
		'Darkmarket';
		'Grand Feast';
	};
	moons = {
		'Moon of Lurking Shadow';
		'Moon of Wandering Flame';
		"Wandwright's Moon";
		'Moon of Dark Waters';
		"Shipwright's Moon";
		'Moon of Singing Boughs';
		'Moon of the Golden Tower';
		"Spellwright's Moon";
		'Moon of Joysome Harvest';
		"Alchemist's Moon";
	};
	moon_abbr = {
		'MS', 'WF', 'WM', 'DM';
		'SM', 'SB', 'GT', 'Sp.';
		'JH', 'AM';
	};
}

local elerian = {
	days = {

	};
	weeks = {
		'First Week', 'Second Week', 'Third Week';
		'Fourth Week', 'Fifth Week', 'Sixth Week';
	};
	moons = {
		'Springrise';
		'Springfall';
		'Summerrise';
		'Summerfall';
		'Autumnrise';
		'Autumnfall';
		'Winterrise';
		'Winterfall';
	};
}

local adjs = {
	'Whimpering'; 'Overturned'; 'Silent'; 'Whimsical'; 'Turbulent';
	'Parsimonius'; 'Rhadamanthine'; 'Exuberant'; 'Winsome';
	'Bifurcated'; 'Shivering'; 'Splendorous'; 'Magnificent';
	'Luminous'; 'Mouthy'; 'Wandering'; 'Vexatious'; 'Irksome';
	'Wrathsome'; 'Fearsome'; 'Wretched'; 'Rambling'; 'Feculent';
	'Insipid'; 'Mad'; 'Eternal'; 'Deathless'; 'Suppurating';
	'Radiant'; 'Trembling'; 'Tremulous'; 'Incredulous'; 'False';
	'Rambunctious';
}

local nouns = {
	'Princeling'; 'Applecart'; 'Oxcart'; 'Parsnip'; 'Lotus';
	'Daffodil'; 'Slave'; 'Ass'; 'Mare'; 'Stallion';

	{false,'Fortitude'};{false,'Providence'};
	{false,'Provocation'};{false,'Wisdom'};
	{false,'Perseverance'};{false,'Destruction'};
	{false,'Suppuration'};{false,'Terror'};
	{false,'Despair'};{false,'Glory'};
}

local yg = function(y)
	local pos = -3
	local neg = y < 0
	y = tostring(math.abs(y))
	local n = ''
	while true do
		local w = string.sub(y,pos,pos+2)
		if w == nil or w == '' then break end 
		n = w .. ',' .. n
		pos = pos - 3
	end
	if neg then n = '-' .. n end
	return string.sub(n,1,-2)
end

local classicyear = function(y)
	local aofs,nofs = (y % 7),(y % 9)
	local adj = adjs[(y*aofs) % #adjs + 1]
	local noun = nouns[(y*nofs) % #nouns + 1]
	if type(noun) == 'table' then
		noun = noun[2]
		if noun[1] then adj = 'the ' .. adj end
	else
		adj = 'the ' .. adj
	end
	return string.format('Year of %s %s', adj, noun)
end

return {
	days_per_stellar_cycle = 17;
	days_per_lunar_cycle = 32;
	default = 'imperial';
	styles = {
		imperial = sorcery.lib.tbl.merge(imperial, {
			name = 'Imperial Archipelagian Calendar';
			longdate = function(date)
				local day  = imperial.days [date.day_of_week ]
				local week = imperial.weeks[date.week_of_moon]
				local moon = imperial.moons[date.moon_of_year]
				return string.format('%s on %s in %s after %s years of the Imperial Revolution in the %s',day,week,moon,yg(date.year),classicyear(date.year))
			end;
			yearname = classicyear;
			shortdate = function(date)
				return string.format('%u/%u I.R. %s', date.day_of_moon, date.moon_of_year, yg(date.year))
			end;
		});
		magisterial = sorcery.lib.tbl.merge(magisterial, {
			name = 'Old Magisterial Calendar';
			yearname = classicyear;
			longdate = function(date)
				local d,w,m = magisterial.days [date.day_of_week ],
				              magisterial.weeks[date.week_of_moon],
				              magisterial.moons[date.moon_of_year]
				if w ~= 'Grand Feast' then
					local n = ({Shortmarket = 'Short'; Longmarket = 'Long'})[d]
					if n ~= nil then
						return string.format('Day of the %s %s beneath the %s in the %s',n,w,m,classicyear(date.year))
					end
				end

				return string.format('%s in the week of the %s beneath the %s in the %s',d,w,m,classicyear(date.year))
			end;
			shortdate = function(date)
				local l = (({Shortmarket = 'S'; Longmarket = 'L'})[magisterial.days[date.day_of_week]]) or tostring(date.day_of_week)
				return string.format('%s-%s %s %sm', l,
					magisterial.weeks[date.week_of_moon],
					magisterial.moon_abbr[date.moon_of_year],
					yg(date.year+1390))
			end;
		});
	}
}
