-- {"ver":"2.0.6","author":"TechnoJo4, Doomsdayrs","dep":["url"]}

-- rename this if you ever figure out its real name

---@type fun(tbl: table , url: string): string
local qs = Require("url").querystring

local text = function(v)
	return v:text()
end

local defaults = {
	meta_offset = 1,
	ajax_hot = "/ajax/hot-novels",
	ajax_latest = "/ajax/latest-novels",
	ajax_chapters = "/ajax/chapter-option",
	appendURLToInfoImage = true,
	searchTitleSel = ".novel-title",

	hasCloudFlare = false,
	hasSearch = true,
	chapterType = ChapterType.HTML
}

function defaults:search(data)
	-- search gives covers but they're in some weird aspect ratio
	local doc = GETDocument(qs({ keyword = data[QUERY], page = data[PAGE] }, self.baseURL .. "/search"))

	return map(doc:selectFirst("div." .. self.searchListSel):select("div.row"), function(v)
			local novel = Novel()
			novel:setImageURL(v:selectFirst("img.cover"):attr("src"))
			local d = v:selectFirst(self.searchTitleSel .. " a")
			novel:setLink(d:attr("href"))
			novel:setTitle(d:attr("title"))
			return novel
		end)
end

function defaults:getPassage(url)
	local htmlElement = GETDocument(self.baseURL..url):selectFirst("div#chapter")
	local title = htmlElement:selectFirst("a.chapter-title"):text()
	htmlElement = htmlElement:selectFirst("div#chapter-content")

	-- Remove/modify unwanted HTML elements to get a clean webpage.
	htmlElement:removeAttr("style") -- Hopefully only temporary as a hotfix
	htmlElement:select("script"):remove()
	htmlElement:select("ins"):remove()
	htmlElement:select("div.ads"):remove()
	htmlElement:select("div[align=\"left\"]:last-child"):remove() -- Report error text

	-- Chapter title inserted before chapter text.
	htmlElement:child(0):before("<h1>" .. title .. "</h1>");

	return pageOfElem(htmlElement)
end

function defaults:parseNovel(url, loadChapters)
	local doc = GETDocument(self.baseURL..url)
	local info = NovelInfo()

	local elem = doc:selectFirst(".info"):children()
	info:setTitle(doc:selectFirst("h3.title"):text())

	local meta_offset = elem:size() < 3 and self.meta_offset or 0

	local function meta_links(i)
		return map(elem:get(meta_offset + i):select("a"), text)
	end

	info:setAuthors(meta_links(0))
	info:setAlternativeTitles(meta_links(1))
	info:setGenres(meta_links(2))
	info:setStatus( ({
		Ongoing = NovelStatus.PUBLISHING,
		Completed = NovelStatus.COMPLETED
	})[elem:get(meta_offset + 4):select("a"):text()] )

	info:setImageURL((self.appendURLToInfoImage and self.baseURL or "") .. doc:selectFirst("div.book img"):attr("src"))
	info:setDescription(table.concat(map(doc:select("div.desc-text p"), text), "\n"))

	if loadChapters then
		local id = doc:selectFirst("div[data-novel-id]"):attr("data-novel-id")
		local i = 0
		info:setChapters(AsList(map(
				GETDocument(qs({ novelId = id,currentChapterId = "" }, self.ajax_base .. self.ajax_chapters)):selectFirst("select"):children(),
				function(v)
					local chap = NovelChapter()
					chap:setLink(self.shrinkURL(v:attr("value")))
					chap:setTitle(v:text())
					chap:setOrder(i)
					i = i + 1
					return chap
				end)))
	end

	return info
end

---@param url string
function defaults:shrinkURL(url)
	return url:gsub(self.baseURL, "")
end

---@param url string
function defaults:expandURL(url)
	return self.baseURL .. url
end

return function(baseURL, _self)
	_self = setmetatable(_self or {}, { __index = function(_, k)
		local d = defaults[k]
		return (type(d) == "function" and wrap(_self, d) or d)
	end })
	_self["baseURL"] = baseURL
	if not _self["ajax_base"] then
		_self["ajax_base"] = baseURL
	end
	_self["listings"] = {
		Listing("Hot", false, function()
			return map(GETDocument(_self.ajax_base .. _self.ajax_hot):select("div.item a"), function(v)
				local novel = Novel()
				novel:setImageURL(baseURL .. v:selectFirst("img"):attr("src"))
				novel:setTitle(v:attr("title"))
				novel:setLink(v:attr("href"))
				return novel
			end)
		end),
		Listing("Latest", false, function()
			return map(GETDocument(_self.ajax_base .. _self.ajax_latest):select("div.row .col-title a"), function(v)
				local novel = Novel()
				novel:setTitle(v:text())
				novel:setLink(v:attr("href"))
				return novel
			end)
		end)
	}
	return _self
end
