--[[
 				 `/shdmmmmmmmmmd-`ymmmddyo:`       //                sm- /h/                        --
				`yNMMMMMMMMMMMMm-.dMMMMMMMMMN+     `MN  `-:::.`   .-:-hM- -o-  .-::.  .::-.   `.:::` MN--. `-::-.
				yMMMMMMMMMMMMMd.:NMMMMMMMMMMMM+    `MN  yMs+oNh  oNy++mM- +Mo -Mm++:`hmo+yN+ .dmo++- MNoo/ `o+odN:
				yMMMMMMMMMMMMy`+NMMMMMMMMMMMMM+    `MN  yM:  dM. MN   yM- +Mo -Mh   /Mmss    sM+     MN    +h ohMo
				`yNMMMMMMMMMo`sMMMMMMMMMMMMMNo     `MN  yM:  dM. oNy//dM- +Mo -Mh   `dNs++o. -mm+//- dM+/+ mN+/sMo
				  `/shddddd/ odddddddddddho:`       ::  .:`  -:   `:///-` .:. `:-     .://:`  `-///. `-//: `-///:.

		Licensed under GNU General Public License v3.0
]]
-- Monitor Focus/Zoom Engine, bundled with Xinu & other monitor accessories
-- Used to zoom precisely into a monitor's screen (and sometimes allowing for use of near click/dragdetectors.
-- Made with <3 love by @SloppyBelloMigliore1 & Indirecta
-- Multi-Face and FOV Adjustment added by @chrischrome
-- Last Edit: 17/09/2024 dd/mm/yyyy

-- !! PLACE IN game>StarterPlayer>StarterPlayerScripts !!

local configuration = {
	["ORIGINAL_FOV"] = 70; -- The FOV with which the player will be reverted after clicking again on a monitor
	["MAX_ACTIVATION_DISTANCE"] = 10; -- The max activation distance the click detectors on the monitors should use
	["MONITOR_TAG"] = "Monitor"; -- CollectionService Tag that this script should use to look for interactable monitors
	["INIT_DELAY"] = 5; -- Delay before looking for devices, useful if game takes a while to load
};

local faces = {
	["Front"] = {
		move = {0, 0, -10},
		rotate = {0, math.rad(180), 0}
	},
	["Back"] = {
		move = {0, 0, 10},
		rotate = {0, 0, 0}
	},
	["Left"] = {
		move = {-10, 0, 0},
		rotate = {0, math.rad(-90), 0}
	},
	["Right"] = {
		move = {10, 0, 0},
		rotate = {0, math.rad(90), 0}
	},
	["Top"] = {
		move = {0, 10, 0},
		rotate = {math.rad(-90), 0, 0}
	},
	["Bottom"] = {
		move = {0, -10, 0},
		rotate = {math.rad(90), 0, 0}
	}
}

local TweenService = game:GetService("TweenService")
local CollectionService = game:GetService("CollectionService")

local TweenI = TweenInfo.new(0.8, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut)

local latch = false;
local function zoomInto(screen, face, adj)
	local CurrentCamera = workspace.CurrentCamera
	if latch then
		CurrentCamera.CameraType = Enum.CameraType.Scriptable
		TweenService:Create(CurrentCamera, TweenI, {
			FieldOfView = configuration.ORIGINAL_FOV,
		}):Play();
		latch = false
		CurrentCamera.CameraType = Enum.CameraType.Custom
		return
	end
	latch = true
	CurrentCamera.CameraType = Enum.CameraType.Scriptable
	-- Field of View is computed based on GUI Width
	TweenService:Create(CurrentCamera, TweenI, {
		FieldOfView = ((screen.Size.X * 10) / 2) + adj,
		CFrame = screen.CFrame * CFrame.new(unpack(faces[face].move)) * CFrame.Angles(unpack(faces[face].rotate))
	}):Play();
end

local function init()
	for _, obj in CollectionService:GetTagged(configuration.MONITOR_TAG) do
		if obj:FindFirstChild("ZoomClickDetector") then return end;
		if not obj:GetAttribute("ZoomFace") then obj:SetAttribute("ZoomFace", "Front") end
		if not obj:GetAttribute("ZoomAdjust") then obj:SetAttribute("ZoomAdjust", 0) end
		local face = obj:GetAttribute("ZoomFace")
		local adj = obj:GetAttribute("ZoomAdjust")
		if not faces[face] then
			obj:SetAttribute("ZoomFace", "Front")
			error("Zoom Script: " .. obj:GetFullName() .. " has an invalid ZoomFace \"" .. face .. "\" and will not function, Please fix this!", 1)
		else

			local CD = Instance.new("ClickDetector")
			CD.Parent = obj
			CD.Name = "ZoomClickDetector"
			CD.MaxActivationDistance = configuration.MAX_ACTIVATION_DISTANCE;

			CD.MouseClick:Connect(function()
				zoomInto(obj, face, adj)
			end)
		end
	end
end

task.wait(configuration.INIT_DELAY)
CollectionService:GetInstanceAddedSignal(configuration.MONITOR_TAG):Connect(init);
init();