from functools import wraps

from .tcr_error import error


def apostrophe_s(word: str):
	"""### Adds 's to a word unless it ends with s, then it adds only the apostrphe '.

	```py
	>>> apostrophe_s('Mark')
	"Mark's"
	>>> apostrophe_s('James')
	"James'"
	"""
	if word.endswith("s"):
		return word + "'"
	return word + "'s"


def plural_s(n: int, *, s: str = "s"):
	"""Return `'s'` if `n != 1` else `''`."""
	return s if n != 1 else ""


def _caps_deco(func):
	@wraps(func)
	def wrapper(word: str, *args, **kwargs):
		result = func(word, *args, **kwargs)
		if word.isupper():
			return result.upper()
		if word[0].isupper() and word[1:].islower():
			return result[0].upper() + result[1:].lower()
		return result

	return wrapper


irregular_plurals = {
	"child": "children",
	"man": "men",
	"woman": "women",
	"tooth": "teeth",
	"foot": "feet",
	"goose": "geese",
	"mouse": "mice",
	"ox": "oxen",
	"person": "people",
	"die": "dice",
	"criterion": "criteria",
	"phenomenon": "phenomena",
	"cactus": "cacti",
	"focus": "foci",
	"analysis": "analyses",
	"thesis": "theses",
	"crisis": "crises",
	"basis": "bases",
	"stimulus": "stimuli",
	"appendix": "appendices",
	"bacterium": "bacteria",
	"curriculum": "curricula",
	"index": "indices",
	"medium": "media",
	"millennium": "millennia",
	"radius": "radii",
	"memorandum": "memoranda",
	"vertex": "vertices",
	"belief": "beliefs",
	"chief": "chiefs",
	"roof": "roofs",
}


def make_plural(word: str, n: int = 2) -> str:
	"""### Tries its best to convert the word to plural if n != 1 else return the original word."""
	if n == 1:
		return word
	if word.lower() in irregular_plurals:
		return irregular_plurals[word.lower()]
	if word.lower().endswith(("s", "x", "z", "ch", "sh", "o")):
		return word + "es"
	if word.lower().endswith("y") and word[-2] not in "aeiou":
		return word[:-1] + "ies"
	if word.lower().endswith("f"):
		return word[:-1] + "ves"
	if word.lower().endswith("fe"):
		return word[:-2] + "ves"
	return word + "s"


globals()["make_plural"] = _caps_deco(make_plural)


def nth(n: int):
	"""### Return a string containing original number + numeric suffix (st, nd, rd, th).

	Takes into account edge cases like 11, 12.
	Supports negative numbers & zero.

	Examples:
	```py
	>>> nth(1)
	'1st'
	>>> nth(4)
	'4th'
	>>> nth(12)
	'12th'
	```
	"""
	if not isinstance(n, int):
		raise error.NotIntegerError(n)

	if n < 0:
		return "-" + nth(-n)

	if 10 < n % 100 < 14:
		suffix = "th"
	else:
		match n % 10:
			case 1:
				suffix = "st"
			case 2:
				suffix = "nd"
			case 3:
				suffix = "rd"
			case _:
				suffix = "th"

	return str(n) + suffix
