---@class Parser
Parser = {
	getLatestManga = nil,
	getPopularManga = nil,
	getChapters = nil,
	prepareChapter = nil,
	loadChapterPage = nil,
	getMangaUrl = nil
}

---Hash table with all parsers
local parserTable = {}
---Cached Parser List
local cachedList = {}

---Local variable used in Parser functions
local is_parsers_list_updated = false

local listDirectory = System.listDirectory
local doesDirExist = System.doesDirExist
local deleteFile = System.deleteFile

---@param Name string
---@param Link string
---@param Lang string
---@param ID integer
---@return Parser
---Creates/Updates Parser Object
function Parser:new(Name, Link, Lang, ID, Version)
	local p = {
		Name = Name,
		Link = Link,
		Lang = Lang,
		ID = ID,
		Version = Version or 0,
		isChanged = 0,
		Disabled = false
	}
	setmetatable(p, self)
	self.__index = self
	if parserTable[ID] and parserTable[ID].Version < p.Version then
		p.isUpdated = true
		p.isChanged = 1
	elseif parserTable[ID] == nil and LAUNCHED then
		p.isNew = true
		p.isChanged = 2
	end
	local message = 'Parser "' .. Name .. '" ' .. (parserTable[ID] and "Updated!" or "Loaded!") .. "!"
	Console.write(message)
	parserTable[ID] = p
	is_parsers_list_updated = true
	return p
end

---@param ID integer
---@return Parser
---Gives Parser Object by `ID`
function GetParserByID(ID)
	return parserTable[ID]
end

---@return table
---Gives Parser List
function GetParserList()
	if not is_parsers_list_updated then
		return cachedList
	end
	is_parsers_list_updated = false
	local list = {}
	for _, v in pairs(parserTable) do
		if (Settings.NSFW and v.NSFW or not v.NSFW) and not v.Disabled and (Settings.ParserLanguage == "DIF" or v.Lang == Settings.ParserLanguage or v.Lang == "DIF" or ((Settings.ParserLanguage == "CHN" or Settings.ParserLanguage == "JAP") and v.Lang == "RAW")) then
			list[#list + 1] = v
		end
	end
	cachedList = list
	table.sort(
		list,
		function(a, b)
			if Settings.FavouriteParsers[a.ID] == Settings.FavouriteParsers[b.ID] then
				if a.isChanged ~= b.isChanged then
					return a.isChanged > b.isChanged
				else
					return string.upper(a.ID) < string.upper(b.ID)
				end
			else
				return Settings.FavouriteParsers[a.ID] == true
			end
		end
	)
	return list
end

function GetParserLanguages()
	local t = {}
	for _, v in pairs(parserTable) do
		if not v.Disabled then
			t[v.Lang] = true
		end
	end
	t["DIF"] = nil
	if t["RAW"] then
		t["CHN"] = true
		t["JAP"] = true
	end
	t["RAW"] = nil
	local newLanguageList = {}
	for k, _ in pairs(t) do
		newLanguageList[#newLanguageList + 1] = k
	end
	table.sort(
		newLanguageList,
		function(a, b)
			return a < b
		end
	)
	table.insert(newLanguageList, 1, "DIF")
	return newLanguageList
end

---Sets update flag to `true`, for regenerating parsers list
function ChangeNSFW()
	is_parsers_list_updated = true
end

---Deletes all parsers and their files
function ClearParsers()
	if doesDirExist("ux0:data/noboru/parsers") then
		local list = listDirectory("ux0:/data/noboru/parsers") or {}
		for i = 1, #list do
			local v = list[i]
			if not v.directory then
				deleteFile("ux0:data/noboru/parsers/" .. v.name)
			end
		end
	end
	--[[
    parserTable = {}
    cachedList = {}]]
	for _, v in pairs(parserTable) do
		v.Disabled = true
	end
	is_parsers_list_updated = true
end
