if not sorcery then
	sorcery = {
		lib = { tbl=dofile('lib/tbl.lua') };
	}
	sorcery.data = {
		calendar = dofile('data/calendar.lua');
		signs = dofile('data/signs.lua');
	}
end

sorcery.calendar = {
	moon_phases = {
		[0] = 'New';
		[0.125] = 'Waxing Crescent';
		[0.25] = 'First Quarter';
		[0.375] = 'Waxing Gibbous';
		[0.5] = 'Full';
		[0.625] = 'Waning Gibbous';
		[0.75] = 'Last Quarter';
		[0.875] = 'Waning Crescent';
	};
	timesofday = {
		[0.00] = 'Midnight';
		[0.10] = 'Early Morning';
		[0.25] = 'Morning';
		[0.50] = 'Noon';
		[0.65] = 'Afternoon';
		[0.80] = 'Evening';
		[0.90] = 'Late Evening';
	};
}

sorcery.calendar.contmatch = function(tbl,f)
	local r
	if f>=1 then f = f - math.floor(f) end
	sorcery.lib.tbl.each_o(tbl, function(phase,point)
		if point <= f
			then r=phase
			else return nil, false
		end
	end)
	return r
end

sorcery.calendar.stats = function(style)
	if not style then style = sorcery.data.calendar.default end
	local s = sorcery.data.calendar.styles[style]
	local days, moons, weeks = s.days, s.moons, s.weeks

	return {
		days_in_year = #moons * #weeks * #days;
		days_in_week = #days;
		days_in_moon = #days * #weeks;
		weeks_in_moon = #weeks;
		weeks_in_year = #weeks * #moons;
		moons_in_year = #moons;
	}
end

sorcery.calendar.date = function(day,style)
	local s = sorcery.calendar.stats(style)

	local day_of_year = day % s.days_in_year;
	local day_of_moon = day_of_year % s.days_in_moon;
	local day_of_week = day_of_moon % s.days_in_week;
	local moon_days = sorcery.data.calendar.days_per_lunar_cycle

	return {
		day_of_year = 1 + day_of_year;
		day_of_moon = 1 + day_of_moon;
		day_of_week = 1 + day_of_week;
		week_of_moon = 1 + math.floor(day_of_moon / s.days_in_week);
		week_of_year = 1 + math.floor(day_of_year / s.days_in_week);
		moon_of_year = 1 + math.floor(day_of_year / s.days_in_moon);
		year = math.floor(day / s.days_in_year);
		moons_passed = math.floor(day / s.days_in_moon);
		weeks_passed = math.floor(day / s.days_in_week);
		lunar_cycle = 1 + math.floor(day / moon_days);
		lunar_phase = (day % moon_days) / moon_days;
	}
end

sorcery.calendar.stars = function(day)
	local periods = math.floor(day / sorcery.data.calendar.days_per_stellar_cycle)

	local elapsed = 0
	local cycle = 1
	while true do
		for _, c in pairs(sorcery.data.signs) do
			if c.cycle then
				if cycle % c.cycle ~= 0 then goto skip end
			end
			elapsed = elapsed + c.duration
			if elapsed >= periods then
				return {
					sign = c;
					cycle = cycle;
				}
			end
		::skip::end
		cycle = cycle + 1
	end
end

sorcery.calendar.longdate = function(day,style)
	if not style then style = sorcery.data.calendar.default end
	return sorcery.data.calendar.styles[style].longdate(sorcery.calendar.date(day,style))
end

sorcery.calendar.shortdate = function(day,style)
	if not style then style = sorcery.data.calendar.default end
	return sorcery.data.calendar.styles[style].shortdate(sorcery.calendar.date(day,style))
end

sorcery.calendar.stardate = function(day)
	local s = sorcery.calendar.stars(day)
	return string.format('sign of the %s, stellar cycle %u', s.sign.patron, s.cycle)
end

-- math.randomseed(os.time())
-- local d = math.random(500,256000)
-- print(string.format('%s :: %s under the %s',
-- 	sorcery.calendar.shortdate(d,'magisterial'),
-- 	sorcery.calendar.longdate(d,'magisterial'),
-- 	sorcery.calendar.stardate(d)))
