--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| 	Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]


local PLUGIN = PLUGIN
PLUGIN.apartments = PLUGIN.apartments or {}

-- A function to get an apartment name
function PLUGIN:SetApartmentNames(tApartments)
	for _, ent in pairs(ents.GetAll()) do
		if !ent:GetClass():find("door") then continue end
		ent.doorName = nil
		ent.doorType = nil

		for _, tInfo in pairs(tApartments) do
			for _, doorIndex in pairs(tInfo.doors) do
				if doorIndex == ent:EntIndex() then
					ent.doorName = tInfo.name
					ent.doorType = tInfo.type
				end
			end
		end
	end
end

function PLUGIN:GetApartmentName(appID)
	netstream.Start("RequestApartmentNames", appID)
end

function PLUGIN:GetApartmentNameDatafile(appID)
	netstream.Start("RequestApartmentNamesDatafile", appID)
end

function PLUGIN:InitPostEntity()
	netstream.Start("RequestApartmentNames")
end

function PLUGIN:ConvertStringRequestToComboselect(requestPanel, comboValue, comboPopulate, callback)
	for i = 1, 2 do
		requestPanel:GetChildren()[5]:GetChildren()[i]:Remove()
	end

	local comboBox = requestPanel:Add("DComboBox")
	comboBox:SetValue(comboValue or "")
	comboBox:SetFont("MenuFontNoClamp")
	comboBox:Dock(TOP)
	comboBox:SetTall(SScaleMin(30 / 3))
	comboBox:DockMargin(0, SScaleMin(20 / 3), 0, 0)
	comboBox.Paint = function(this, w, h)
		surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
		surface.DrawOutlinedRect(0, 0, w, h)
	end

	comboPopulate(comboBox)

	requestPanel:GetChildren()[6]:GetChildren()[1].DoClick = function()
		callback(comboBox)
		requestPanel:Close()
	end

	requestPanel.Think = function(this)
		if IsValid(comboBox.Menu) and comboBox.Menu:IsVisible() then return end
		this:MoveToFront()
	end
end

-- A function to register the apartments ESP
do
	local priColor = Color(191, 91, 81, 255)
	local shopColor = Color(193, 136, 79, 255)
	local normColor = Color(185, 122, 87, 255)
	local center = TEXT_ALIGN_CENTER
    local function apartmentsESP(client, entity, x, y, factor)
		if !entity.doorName or !entity.doorType then return end

		local type = entity.doorType
		local espcol = (type == "priority" and priColor or type == "shop" and shopColor or normColor)
        ix.util.DrawText("APP : "..entity.doorName.." | "..string.upper(entity.doorType), x, y - math.max(10, 32 * factor), espcol, center, center, nil, math.max(255 * factor, 80))
    end

    ix.observer:RegisterESPType("func_door", apartmentsESP, "apartments")
	ix.observer:RegisterESPType("func_door_rotating", apartmentsESP, "apartments")
	ix.observer:RegisterESPType("prop_door_rotating", apartmentsESP, "apartments")
	ix.observer:RegisterESPType("prop_dynamic", apartmentsESP, "apartments")
end

-- Clientside hook to Sync App names, types and doors (for ESP)
netstream.Hook("SyncApartments", function(tApartments, bNoSetNames, bDatafile)
	for appID, tApartment in pairs(tApartments) do
		if PLUGIN.apartments[appID] then continue end

		PLUGIN.apartments[appID] = tApartment
	end

	if !bNoSetNames then
		PLUGIN:SetApartmentNames(tApartments)
	end

	if !bDatafile then return end
	if IsValid(ix.gui.datafileHousingInfo) and ix.gui.datafileHousingInfo.CreateHousingRow then
		ix.gui.datafileHousingInfo:CreateHousingRow(tApartments)
	end
end)

netstream.Hook("SyncApartmentsToDatapad", function(tApartments)
	PLUGIN.apartments = tApartments
	if !IsValid(ix.gui.apartments) then return end
	if !ix.gui.apartments.CreateApartments then return end

	if !tApartments or tApartments and !istable(tApartments) then return end
	if #tApartments == 0 then
		ix.gui.apartments.curCollect = ix.gui.apartments.curCollect - 5
		return
	end
	
	ix.gui.apartments:ClearContent()

	local normalHousing = {}
	local shops = {}

	for _, tApartment in pairs(tApartments) do
		local appID = tApartment.appID or 1

		if tApartment.type == "shop" then
			shops[appID] = tApartment
			continue
		end

		normalHousing[appID] = tApartment
	end

	ix.gui.apartments:CreateApartments(normalHousing, function(panel, combineutilities)
		panel:Dock(TOP)
		panel:SetTall(ix.gui.apartments:GetParent():GetTall() * 0.5 - ix.gui.apartments.apartmentsFrame:GetTall())
		panel:DockMargin(0, 0, 0, SScaleMin(10 / 3))

		ix.gui.apartments.shopsFrame = ix.gui.apartments:Add("EditablePanel")
		combineutilities:CreateTitle(ix.gui.apartments.shopsFrame, ix.gui.apartments, "shop")

		local decrementApartments, incrementApartments = ix.gui.apartments.shopsFrame:Add("DButton"), ix.gui.apartments.shopsFrame:Add("DButton")
		combineutilities:CreateTitleFrameRightTextButton(incrementApartments, ix.gui.apartments.shopsFrame, 87, "page suivante", RIGHT)
		incrementApartments:SetZPos(2)
		combineutilities:CreateTitleFrameRightTextButton(decrementApartments, ix.gui.apartments.shopsFrame, 87, "page précédente", RIGHT)
		decrementApartments:SetZPos(3)
		incrementApartments:DockMargin(SScaleMin(20 / 3), 0, 0 - SScaleMin(3 / 3), SScaleMin(6 / 3))
	
		ix.gui.apartments.nextClick = CurTime()
	
		decrementApartments.DoClick = function()
			if ix.gui.apartments.nextClick > CurTime() then return end
	
			ix.gui.apartments.curCollect = math.max(ix.gui.apartments.curCollect - 5, 5)
			ix.gui.apartments:GetApartments(ix.gui.apartments.curCollect)
	
			ix.gui.apartments.nextClick = CurTime() + 1
		end
	
		incrementApartments.DoClick = function()
			if ix.gui.apartments.nextClick > CurTime() then return end
	
			ix.gui.apartments.curCollect = ix.gui.apartments.curCollect + 5
			ix.gui.apartments:GetApartments(ix.gui.apartments.curCollect)
	
			ix.gui.apartments.nextClick = CurTime() + 1
		end

		ix.gui.apartments.content2 = ix.gui.apartments:Add("DScrollPanel")
		ix.gui.apartments.content2:Dock(FILL)

		ix.gui.apartments:CreateApartments(shops, false, true)
	end)
end)

netstream.Hook("UpdateIndividualApartment", function(appID, tApartment)
	if IsValid(ix.gui.apartments) and ix.gui.apartments.ViewSingleApartment then
		ix.gui.apartments:ViewSingleApartment(appID, tApartment)
	end
end)

local doors = ix.plugin.list["doors"]
if !doors then return end

do
	doors.DrawDoorInfo = function(self, door, width, position, angles, scale, clientPosition)
		local alpha = math.max((1 - clientPosition:DistToSqr(door:GetPos()) / 65536) * 255, 0)

		if (alpha < 1) then
			return
		end

		local info = hook.Run("GetDoorInfo", door) or self:GetDefaultDoorInfo(door)

		if (!istable(info) or table.IsEmpty(info)) then
			return
		end

		-- title + background
		surface.SetFont("WN3D2DLargeText")
		if string.len(info.name) > 23 then
			surface.SetFont("WN3D2DMediumText")
		end
		local nameWidth, nameHeight = surface.GetTextSize(info.name)

		surface.SetTextColor(ColorAlpha(color_white, alpha))
		surface.SetTextPos(-nameWidth * 0.5, -nameHeight * 0.5)
		surface.DrawText(info.name)

		-- description
		local lines = ix.util.WrapText(info.description, width, "ix3D2DSmallFont")
		local y = nameHeight * 0.5 + 4

		for i = 1, #lines do
			local line = lines[i]
			if line:find(L("dIsOwnable")) or line:find(L("dIsNotOwnable")) then return end
			local textWidth, textHeight = surface.GetTextSize(line)

			surface.SetTextPos(-textWidth * 0.5, y)
			surface.DrawText(line)

			y = y + textHeight
		end
	end
end

function PLUGIN:CreateExtraCharacterTabInfo(character, informationSubframe, CreatePart)
	local genericData = character:GetGenericdata()
	local genericHousing = genericData.housing
	if genericHousing then
		netstream.Start("RequestApartmentNames", tonumber(genericData.housing))
	end

	local housing = ix.plugin.list["housing"]
	local apartments = housing.apartments or {}

	-- Apartment
	local apartmentPanel = informationSubframe:Add("Panel")
	CreatePart(apartmentPanel, "Logement :", (genericHousing and apartments[tonumber(genericData.housing)] and apartments[tonumber(genericData.housing)].name) or "Aucun", "cid")
end