require('strict') local match = require("Module:String")._match  local p = {}  --- Returns a formatted link to the list of episodes article. --- @param listOfEpisodesArticle string --- @return string local function getListOfEpisodesLink(listOfEpisodesArticle) 	local listOfEpisodesPage = mw.title.new(listOfEpisodesArticle, 0) 	if listOfEpisodesPage and listOfEpisodesPage.exists and listOfEpisodesPage.redirectTarget ~= mw.title.getCurrentTitle() then 		return string.format("পর্বের তালিকা", listOfEpisodesArticle) 	end end  --- Returns an article link. --- @param article string The article's title. --- @param pipedLink string The piped link. --- @return string local function getArticleLink(article, pipedLink) 	if not pipedLink or pipedLink == "" then 		return "" .. article .. "" 	end 	return "" .. pipedLink .. "" end  --- Returns the show name and season number from a title. --- @param showName string The show's title. --- @return nil | number | string, nil | number | string local function getShowNameAndSeasonNumberFromShowName(showName) 	local _, _, showNameModified, seasonNumber = string.find(showName, "(.*)%s+(%d+)$") 	return showNameModified, seasonNumber end  --- Returns the current season number from the disambiguation. --- @param disambiguation string The article's disambiguation. --- @return string local function getCurrentSeasonNumberFromDisambiguation(disambiguation) 	return match(disambiguation , "%d+", 1, -1, false, "") end  --- Returns the type of word used for "season" in the title. --- --- The returned value can be one of three options: "season", "series", "story arc" or "specials". --- @param title string The article's title. --- @return string local function getSeasonType(title) 	for _, seasonType in pairs({"মৌসুম", "ধারাবাহিক", "খণ্ড", "বিশেষ"}) do 		if string.find(title, seasonType) then 			return seasonType 		end 	end 	return "মৌসুম" end  --- Returns the season number from the title. --- @param title string The article's title. --- @return string | nil local function getSeasonNumber(title) 	return match(title , "%d+", 1, -1, false, "") end  --- Returns the disambiguation from the title. --- @param title string The article's title. --- @return string | nil local function getDisambiguation(title) 	local disambiguation = match(title, "%s%((.-)%)", 1, -1, false, "") 	if disambiguation and disambiguation == "" then 		return nil 	end 	return disambiguation end  --- Returns the title without its disambiguation. --- @param title string The article's title. --- @return string | nil local function getTitleWithoutDisambiguation(title) 	local disambiguation = getDisambiguation(title) 	if disambiguation then 		return string.gsub(title, "%(" .. disambiguation  .. "%)", "") 	end 	return title end  --- Returns the TV program's disambiguation. --- @param disambiguation string The disambiguation used in the season's article title. --- @return string local function getTVProgramDisambiguation(disambiguation) 	if not disambiguation then 		return "" 	end  	-- Check if the disambiguation is normal 'season #' or 'series #'. 	-- If so, remove disambiguation. 	if string.match(disambiguation, "^মৌসুম %d*$") or string.match(disambiguation, "^ধারাবাহিক %d*$") then 		return "" 	end  	local disambiguationStyle = " (%s)" 	-- Check if the disambiguation is extended and has 'TV series' and isn't just season #. 	-- Only leave the TV series disambiguation, not including the season #. 	-- Example: Teenage Mutant Ninja Turtles (1987 TV series, season 5) will return '1987 TV series'. 	if string.find(disambiguation, "টেলিভিশন ধারাবাহিক") then 		local shortDisambiguation, _ = disambiguation:match("^(.*),") 		if shortDisambiguation then 			return string.format(disambiguationStyle, shortDisambiguation) 		end 	end  	-- Check if the disambiguation is extended with country adjective. 	-- Example: The Office (American season 2) will return "American season 2". 	-- Keep only country adjective. 	local countryDisambiguation = disambiguation:match("^(.*) মৌসুম %d*") or disambiguation:match("^(.*) ধারাবাহিক %d*") 	local data = mw.loadData("মডিউল:দেশের বিশেষণ") 	local valid_result = data.getCountryFromAdj[countryDisambiguation] 	-- Check if the country adjective is valid. 	if valid_result then 		-- Add 'TV series' suffix 		return string.format(disambiguationStyle, countryDisambiguation .. " টেলিভিশন ধারাবাহিক") 	end  	-- Not a known disambiguation style. Use whatever was used in the title or manually added. 	-- Note: might not be a valid style link. 	return string.format(disambiguationStyle, disambiguation) end  --- Returns the show's name from the title. --- @param title string The article's title. --- @return string local function getShowName(title) 	local name, _ = mw.ustring.gsub(title, "মৌসুম %d*$", "") 	name, _ = mw.ustring.gsub(name, "ধারাবাহিক %d*$", "") 	name, _ = mw.ustring.gsub(name, "বিশেষ", "") 	name, _ = mw.ustring.gsub(name, "খণ্ড %d*$", "") 	name = string.match(name, "^%s*(.-)%s*$") -- Trim spaces. 	return name end  --- Returns "true" if the given link is valid; nil otherwise. --- A link is valid in the following cases: ---	-- A season article exists. ---	-- A redirect exists to a season section. --- --- A link is invalid in the following cases: ---	-- A season article or redirect do not exist. ---	-- A redirect exists, but it is a general redirect and not for any specific season section. --- --- Note: Return values are not booleans as the returned value is used in template space. --- @param title string The article's title. --- @return string | nil local function isLinkValid(title) 	local article = mw.title.new(title)  	-- Article or redirect do not exist; Not a valid link. 	if not article or not article.exists then 		return nil 	end  	local redirectTarget = article.redirectTarget  	-- Article exists and is not a redirect; Valid link. 	if not redirectTarget then 		return "true" 	end  	local fullLink = redirectTarget.fullText 	local isSection = fullLink:find("#")  	-- Article is a section redirect; Valid link. 	if isSection then 		return "true" 	end  	-- Article is a general redirect; Not a valid link. 	return nil end  --- Returns a season article title and a piped link. --- --- The following are the supported season naming styles: ---	--  Style: <showName> <seasonType> <seasonNumber> ---		Example: Lost season 2. ---		Example: Doctor Who series 2. ---	--  Style: <showName> (<country> TV series) <seasonType> <seasonNumber> ---		Example: The Office (American TV series) season 2. ---		Example: Teenage Mutant Ninja Turtles (1987 TV series) season 2 ---		Example: X Factor (British TV series) series 2. ---		Example: Love Island (British TV series) series 2 ---	--  Style: <showName> (<year> TV series) <seasonType> <seasonNumber> ---		Example: Love Island (2015 TV series) series 2 ---	--  Style: <showName> (<country> <seasonType>) ---		Example: Big Brother 2 (American season).  --- @param title string The article's title. --- @param seasonNumberDiff number The number difference between the current season and the other season. --- @return string, string local function getArticleTitleAndPipedLink(title, seasonNumberDiff) 	local seasonType = getSeasonType(title) 	local currentSeasonNumber = getSeasonNumber(title) 	if tonumber(currentSeasonNumber) == nil then 		return "", nil 	end 	local seasonNumber = currentSeasonNumber + seasonNumberDiff 	local modifiedTitle, numberOfReplacements = string.gsub(title, "%d+$", seasonNumber) 	local pipedLink = seasonType:gsub("^%l", string.upper) .. " " .. seasonNumber  	local disambiguation = getDisambiguation(title) 	-- Titles such as "Big Brother 2 (American season) and Teenage Mutant Ninja Turtles (1987 TV series) season 2". 	if disambiguation then 		local titleWithoutDisambiguation = string.gsub(title, disambiguation, "_DAB_") 		modifiedTitle, numberOfReplacements = string.gsub(titleWithoutDisambiguation, "%d+", seasonNumber)  		 -- Articles, such as "Hawaii Five-0 (2010 TV series) season 2", that have a number 		 -- as part of their title will need an additional fix in order for that number not to change. 		if numberOfReplacements > 1 then 			local titleFix = string.match(title, "%d+", 1) 			modifiedTitle = string.gsub(modifiedTitle, "%d+", titleFix, 1) 		end 	 		modifiedTitle = string.gsub(modifiedTitle, "_DAB_", disambiguation) 		return modifiedTitle, pipedLink  	-- Titles such as "Big Brother Brasil 2". 	elseif not string.find(title, seasonType) then 		return modifiedTitle, nil  	-- Invalid usages of TV series articles with the television season infobox. 	elseif disambiguation and string.find(disambiguation, "টেলিভিশন ধারাবাহিক") and not (string.find(disambiguation, ", মৌসুম") or string.find(disambiguation, ", ধারাবাহিক"))  then 		return "", nil  	-- Standard titles such as "Lost season 1". 	else 		return modifiedTitle, pipedLink 	end end  --- Returns the article's title either from args (usually from /testcases) or from the page itself. --- @param frame table The frame invoking the module. --- @return string local function getTitle(frame) 	local getArgs = require("Module:Arguments").getArgs 	local args = getArgs(frame) 	if args.italic_title then 		return "no" 	end 	 	local title = args.title 	if not title then 		title = mw.title.getCurrentTitle().text 	end 	return title end  --- Returns "true" if the given season link is valid; nil otherwise. --- @param frame table The frame invoking the module. --- @param seasonNumberDiff number The number difference between the current season and the other season. --- @return string | nil local function isSeasonLinkValid(frame, seasonNumberDiff) 	local title = getTitle(frame) 	local articleTitle, _ = getArticleTitleAndPipedLink(title, seasonNumberDiff) 	return isLinkValid(articleTitle) end  --- Returns a season article link. --- @param frame table The frame invoking the module. --- @param seasonNumberDiff number The number difference between the current season and the other season. --- @return string local function getSeasonArticleLink(frame, seasonNumberDiff) 	local title = getTitle(frame) 	local articleTitle, pipedLink = getArticleTitleAndPipedLink(title, seasonNumberDiff) 	return getArticleLink(articleTitle, pipedLink) end  --- Returns "true" if the season link for the next season is valid; nil otherwise. --- @param frame table The frame invoking the module. --- @return string | nil function p.isNextSeasonLinkValid(frame) 	return isSeasonLinkValid(frame, 1) end  --- Returns "true" if the season link for the previous season is valid; nil otherwise. --- @param frame table The frame invoking the module. --- @return string | nil function p.isPrevSeasonLinkValid(frame) 	return isSeasonLinkValid(frame, -1) end  --- Returns "true" if the season link for the previous or next season is valid; nil otherwise. --- @param frame table The frame invoking the module. --- @return string | nil function p.isPrevOrNextSeasonLinkValid(frame) 	if p.isPrevSeasonLinkValid(frame) == "true" then 		return "true" 	end 	return p.isNextSeasonLinkValid(frame) end  --- Returns the next season article title. --- @param frame table The frame invoking the module. --- @return string function p.getNextSeasonArticle(frame) 	return getSeasonArticleLink(frame, 1) end  --- Returns the previous season article title. --- @param frame table The frame invoking the module. --- @return string function p.getPrevSeasonArticle(frame) 	return getSeasonArticleLink(frame, -1) end  --- Returns the type of season word used - "season" or "series". --- @param frame table The frame invoking the module. --- @return string function p.getSeasonWord(frame) 	local title = getTitle(frame) 	title = getTitleWithoutDisambiguation(title) 	local seasonType = getSeasonType(title) 	return seasonType end  --- Returns an  instance if title qualifies or a blank string.  --- @param frame table --- @return string function p.getItalicTitle(frame) 	local getArgs = require("Module:Arguments").getArgs 	local args = getArgs(frame) 	 	-- If italic_title is set then "no" is the only valid value. 	-- Don't set an italic title. 	if args.italic_title then 		return "" 	end  	local title = getTitle(frame) 	title = getShowName(getTitleWithoutDisambiguation(title))  	-- If the infobox is used on List of articles don't set an italic title. 	-- TODO: this can be fixed in the future but current usages use a manual display title. 	if string.find(title, "তালিকা") then 		return "" 	end  	return frame:expandTemplate{title = "Italic title", args = {string = title}} end  --- Returns the text used for the |above= field of the infobox. --- --- @param frame table --- @return string function p.getAboveTitle(frame) 	local getArgs = require("Module:Arguments").getArgs 	local args = getArgs(frame) 	local title = getTitle(frame) 	title = getShowName(getTitleWithoutDisambiguation(title)) 	return title end  --- Returns the text used for the |subheader= field of the infobox. --- --- The text is returned in the format of "Season #" or "Series #", --- depending on either what the article disambiguation uses, or on the manually entered parameters of the infobox. --- @param frame table The frame invoking the module. --- @return string | nil function p.getSubHeader(frame) 	local getArgs = require("Module:Arguments").getArgs 	local args = getArgs(frame)  	local seasonType 	local seasonNumber 	if args.season_number then 		seasonType = "মৌসুম" 		seasonNumber = args.season_number 	elseif args.series_number then 		seasonType = "ধারাবাহিক" 		seasonNumber = args.series_number 	end  	if not seasonNumber then 		local title = getTitle(frame) 		local titleWithoutDisambiguation = getTitleWithoutDisambiguation(title) 		seasonNumber = getSeasonNumber(titleWithoutDisambiguation) 		seasonType = getSeasonType(titleWithoutDisambiguation) 		 		-- For pages like "Doctor Who specials (2008–2010)". 		if seasonType == "বিশেষ" then 			local disambiguation = getDisambiguation(title) or "" 			return disambiguation .. " " .. seasonType 		end 		seasonType = seasonType:sub(1, 1):upper() .. seasonType:sub(2) 	end  	if seasonNumber and seasonNumber ~= "" then 		return seasonType .. " " .. seasonNumber 	end  	return nil end  --- Returns a formatted link to the list of episodes article. --- --- The returned link is in the style of: --- [List of <series name> <disambiguation, if present> episodes <range, if present>|List of episodes] --- --- The link will only return if the page exists. --- @param frame table The frame invoking the module. --- @return string | nil function p.getListOfEpisodes(frame) 	local getArgs = require("Module:Arguments").getArgs 	local args = getArgs(frame)  	if args.link then 		-- Parameter should be unformatted. 		if string.find(args.link, "%[") then 			local delink = require("Module:Delink")._delink 			args.link = delink({args.link, wikilinks = "target"}) 		end  		return getListOfEpisodesLink(args.link) 	end  	local title = getTitle(frame) 	local showName = getShowName(getTitleWithoutDisambiguation(title)) 	if showName then 		local disambiguation = getDisambiguation(title) 		if disambiguation then 			disambiguation = " (" .. disambiguation .. ")" 		end 		local listOfEpisodesArticle = string.format("%s%s-এর পর্বের তালিকা", showName, disambiguation or "") 		return getListOfEpisodesLink(listOfEpisodesArticle) 	end end  return p