--[[
| 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 PANEL = vgui.Register("pac_dtree_node_button", {}, "DButton")
pace.pac_dtree_node_button = PANEL

function PANEL:Init()
	self:SetTextInset(32, 0)
	self:SetContentAlignment(4)
end

function PANEL:Paint(w, h)
	derma.SkinHook("Paint", "TreeNodeButton", self, w, h)
	return false
end

function PANEL:UpdateColours(skin)
	if self:IsSelected() then return self:SetTextStyleColor(skin.Colours.Tree.Selected) end
	if self.Hovered then return self:SetTextStyleColor(skin.Colours.Tree.Hover) end

	return self:SetTextStyleColor(skin.Colours.Tree.Normal)
end

local PANEL = vgui.Register("pac_dtree", {}, "DScrollPanel")
pace.pac_dtree = PANEL

AccessorFunc(PANEL, "m_bShowIcons",             "ShowIcons")
AccessorFunc(PANEL, "m_iIndentSize",            "IndentSize")
AccessorFunc(PANEL, "m_iLineHeight",            "LineHeight")
AccessorFunc(PANEL, "m_pSelectedItem",          "SelectedItem")
AccessorFunc(PANEL, "m_bClickOnDragHover",      "ClickOnDragHover")

function PANEL:Init()
	self:SetShowIcons(true)
	self:SetIndentSize(14)
	self:SetLineHeight(17)

	self.RootNode = self:GetCanvas():Add("pac_dtree_node")
	self.RootNode:SetRoot(self)
	self.RootNode:SetParentNode(self)
	self.RootNode:SetSize(5,5)
	self.RootNode:Dock(TOP)
	self.RootNode:SetText("")
	self.RootNode:SetExpanded(true, true)
	self.RootNode:DockMargin(0, 0, 0, 0)

	self:SetPaintBackground(true)
end

function PANEL:Root()
	return self.RootNode
end

function PANEL:AddNode(strName, strIcon)
	return self.RootNode:AddNode(strName, strIcon)
end

function PANEL:ChildExpanded(bExpand)
	self:InvalidateLayout()
end

function PANEL:ShowIcons()
	return self.m_bShowIcons
end

function PANEL:ExpandTo(bExpand)

end

function PANEL:SetExpanded(bExpand)

end

function PANEL:Clear()

end

function PANEL:Paint(w, h)
	derma.SkinHook("Paint", "Tree", self, w, h)
	return true
end

function PANEL:DoClick(node)
	return false
end

function PANEL:DoRightClick(node)
	return false
end

function PANEL:SetSelectedItem(node)
	if IsValid(self.m_pSelectedItem) then
		self.m_pSelectedItem:SetSelected(false)
		self:OnNodeDeselected(self.m_pSelectedItem)
	end

	self.m_pSelectedItem = node

	if node then
		node:SetSelected(true)
		node:OnNodeSelected(node)
	end
end

function PANEL:OnNodeSelected(node)

end

function PANEL:OnNodeDeselected(node)

end

function PANEL:MoveChildTo(child, pos)
	self:InsertAtTop(child)
end

function PANEL:LayoutTree()
	self:InvalidateChildren(true)
end

local PANEL = vgui.Register("pac_dtree_node", {}, "DPanel")
pace.pac_dtree_node = PANEL

AccessorFunc(PANEL, "m_pRoot",                  "Root")

AccessorFunc(PANEL, "m_pParentNode",            "ParentNode")

AccessorFunc(PANEL, "m_strPathID",              "PathID")
AccessorFunc(PANEL, "m_strWildCard",            "WildCard")
AccessorFunc(PANEL, "m_bNeedsPopulating",       "NeedsPopulating")

AccessorFunc(PANEL, "m_bDirty",                 "Dirty",                FORCE_BOOL)
AccessorFunc(PANEL, "m_bNeedsChildSearch",      "NeedsChildSearch",     FORCE_BOOL)

AccessorFunc(PANEL, "m_bForceShowExpander",     "ForceShowExpander",    FORCE_BOOL)
AccessorFunc(PANEL, "m_bHideExpander",          "HideExpander",         FORCE_BOOL)
AccessorFunc(PANEL, "m_bDoubleClickToOpen",     "DoubleClickToOpen",    FORCE_BOOL)

AccessorFunc(PANEL, "m_bLastChild",             "LastChild",            FORCE_BOOL)
AccessorFunc(PANEL, "m_bDrawLines",             "DrawLines",            FORCE_BOOL)
AccessorFunc(PANEL, "m_strDraggableName",       "DraggableName")

function PANEL:Init()
	self:SetDoubleClickToOpen(true)

	self.Label = vgui.Create("pac_dtree_node_button", self)
	self.Label:SetDragParent(self)
	self.Label.DoClick = function() self:InternalDoClick() end
	self.Label.DoDoubleClick = function() self:InternalDoClick() end
	self.Label.DoRightClick = function() self:InternalDoRightClick() end
	self.Label.DragHover = function(s, t) self:DragHover(t) end

	self.Expander = vgui.Create("DExpandButton", self)
	self.Expander.DoClick = function() self:SetExpanded( not self.m_bExpanded) end
	self.Expander:SetVisible(false)

	self.Icon = vgui.Create("DImage", self)
	self.Icon:SetImage("icon16/folder.png")
	self.Icon:SizeToContents()

	self.fLastClick = SysTime()

	self:SetDrawLines(false)
	self:SetLastChild(false)
end

function PANEL:SetRoot(root)
	self.m_pRoot = root

	root.added_nodes = root.added_nodes or {}
	for i,v in ipairs(root.added_nodes) do
		if v == self then return end
	end
	table.insert(root.added_nodes, self)
end

function PANEL:OnRemove()
	local root = self:GetRoot()

	if not IsValid(root) then return end

	root.added_nodes = root.added_nodes or {}
	for i,v in ipairs(root.added_nodes) do
		if v == self then
			table.remove(root.added_nodes, i)
			break
		end
	end
end

function PANEL:IsRootNode()
	return self.m_pRoot == self.m_pParentNode
end

function PANEL:InternalDoClick()
	self:GetRoot():SetSelectedItem(self)

	if self:DoClick() then return end
	if self:GetRoot():DoClick(self) then return end

	if not self.m_bDoubleClickToOpen or (SysTime() - self.fLastClick < 0.3) then
		self:SetExpanded( not self.m_bExpanded)
	end

	self.fLastClick = SysTime()
end

function PANEL:OnNodeSelected(node)
	local parent = self:GetParentNode()
	if IsValid(parent) and parent.OnNodeSelected then
		parent:OnNodeSelected(node)
	end
end

function PANEL:InternalDoRightClick()
	if self:DoRightClick() then return end
	if self:GetRoot():DoRightClick(self) then return end
end

function PANEL:DoClick()
	return false
end

function PANEL:DoRightClick()
	return false
end

function PANEL:SetIcon(str)
	if not str then return end
	if str == "" then return end

	self.Icon:SetImage(str)
end

function PANEL:ShowIcons()
	return self:GetParentNode():ShowIcons()
end

function PANEL:GetLineHeight()
	return self:GetParentNode():GetLineHeight()
end

function PANEL:GetIndentSize()
	return self:GetParentNode():GetIndentSize()
end

function PANEL:SetText(strName)
	self.Label:SetText(strName)
end

function PANEL:ExpandRecurse(bExpand)
	self:SetExpanded(bExpand, true)

	if not self.ChildNodes then return end

	for k, Child in pairs(self.ChildNodes:GetItems()) do
		if Child.ExpandRecurse then
			Child:ExpandRecurse(bExpand)
		end
	end
end

function PANEL:ExpandTo(bExpand)
	self:SetExpanded(bExpand, true)
	self:GetParentNode():ExpandTo(bExpand)
end


function PANEL:IsExpanded()
	local parent = self:GetParent():GetParent()

	while IsValid(parent) and parent.m_bExpanded ~= nil do
		if parent.m_bExpanded == false then
			return false
		end
		parent = parent:GetParent():GetParent()
	end

	return true
end

function PANEL:SetExpanded(bExpand)

	if self.m_pParentNode:IsValid() then
		self:GetParentNode():ChildExpanded(bExpand)
	end
	self.Expander:SetExpanded(bExpand)
	self.m_bExpanded = bExpand
	self:InvalidateLayout(true)

	if not self.ChildNodes then return end

	local StartTall = self:GetTall()

	if self.ChildNodes then
		self.ChildNodes:SetVisible(bExpand)
		if bExpand then
			self.ChildNodes:InvalidateLayout(true)
		end
	end

	self:InvalidateLayout(true)
end

function PANEL:ChildExpanded(bExpand)
	self.ChildNodes:InvalidateLayout(true)
	self:InvalidateLayout(true)
	self:GetParentNode():ChildExpanded(bExpand)
end

function PANEL:Paint()
end

function PANEL:HasChildren()
	if not IsValid(self.ChildNodes) then return false end
	return self.ChildNodes:HasChildren()
end


function PANEL:DoChildrenOrder()
	if not self.ChildNodes then return end

	local last = table.Count(self.ChildNodes:GetChildren())
	for k, Child in pairs(self.ChildNodes:GetChildren()) do
		Child:SetLastChild(k == last)
	end
end

function PANEL:PerformRootNodeLayout()
	self.Expander:SetVisible(false)
	self.Label:SetVisible(false)
	self.Icon:SetVisible(false)

	if IsValid(self.ChildNodes) then
		self.ChildNodes:Dock(TOP)
		self:SetTall(self.ChildNodes:GetTall())
	end
end

function PANEL:PerformLayout()
	if self:IsRootNode() then
		return self:PerformRootNodeLayout()
	end

	local LineHeight = self:GetLineHeight()

	if self.m_bHideExpander then
		self.Expander:SetPos(-11, 0)
		self.Expander:SetSize(15, 15)
		self.Expander:SetVisible(false)
	else
		self.Expander:SetPos(2, 0)
		self.Expander:SetSize(15, 15)
		self.Expander:SetVisible(self:HasChildren() or self:GetForceShowExpander())
		self.Expander:SetZPos(10)
	end

	self.Label:StretchToParent(0, nil, 0, nil)
	self.Label:SetTall(LineHeight)

	if self:ShowIcons() then
		self.Icon:SetVisible(true)
		self.Icon:SetPos(self.Expander.x + self.Expander:GetWide() + 4, (LineHeight - self.Icon:GetTall()) * 0.5)
		self.Label:SetTextInset(self.Icon.x + self.Icon:GetWide() + 4, 0)
	else
		self.Icon:SetVisible(false)
		self.Label:SetTextInset(self.Expander.x + self.Expander:GetWide() + 4, 0)
	end

	if not self.ChildNodes or not self.ChildNodes:IsVisible() then
		self:SetTall(LineHeight)
	return end

	self.ChildNodes:SizeToContents()
	self:SetTall(LineHeight + self.ChildNodes:GetTall())

	self.ChildNodes:StretchToParent(LineHeight, LineHeight, 0, 0)

	self:DoChildrenOrder()
end

function PANEL:CreateChildNodes()
	if self.ChildNodes then return end

	self.ChildNodes = vgui.Create("DListLayout", self)
	self.ChildNodes:SetDropPos("852")
	self.ChildNodes:SetVisible(self.m_bExpanded)
	self.ChildNodes.OnChildRemoved = function()
		self.ChildNodes:InvalidateLayout()
	end

	self.ChildNodes.OnModified = function()
		self:OnModified()
	end

	self:InvalidateLayout()
end

function PANEL:AddPanel(pPanel)
	self:CreateChildNodes()

	self.ChildNodes:Add(pPanel)
	self:InvalidateLayout()
end

function PANEL:AddNode(strName, strIcon)
	self:CreateChildNodes()

	local pNode = vgui.Create("pac_dtree_node", self)
		pNode:SetText(strName)
		pNode:SetParentNode(self)
		pNode:SetRoot(self:GetRoot())
		pNode:SetIcon(strIcon)
		pNode:SetDrawLines( not self:IsRootNode())

		self:InstallDraggable(pNode)

	self.ChildNodes:Add(pNode)
	self:InvalidateLayout()

	return pNode
end

function PANEL:InsertNode(pNode)
	self:CreateChildNodes()

	pNode:SetParentNode(self)
	pNode:SetRoot(self:GetRoot())
	self:InstallDraggable(pNode)

	self.ChildNodes:Add(pNode)
	self:InvalidateLayout()

	return pNode
end

function PANEL:InstallDraggable(pNode)
	local DragName = self:GetDraggableName()
	if not DragName then return end

	-- Make this node draggable
	pNode:SetDraggableName(DragName)
	pNode:Droppable(DragName)

	-- Allow item dropping onto us
	self.ChildNodes:MakeDroppable(DragName, true, true)
end

function PANEL:DroppedOn(pnl)
	self:InsertNode(pnl)
	self:SetExpanded(true)
end

function PANEL:SetSelected(b)
	self.Label:SetSelected(b)
	self.Label:InvalidateLayout()
	if self.OnSelected then
		self:OnSelected(b)
	end
end

function PANEL:DragHoverClick(HoverTime)
	if not self.m_bExpanded then
		self:SetExpanded(true)
	end

	if self:GetRoot():GetClickOnDragHover() then
		self:InternalDoClick()
	end
end


function PANEL:MoveToTop()
	local parent = self:GetParentNode()
	if not IsValid(parent) then return end

	self:GetParentNode():MoveChildTo(self, 1)
end

function PANEL:MoveChildTo(child)
	self.ChildNodes:InsertAtTop(child)
end

function PANEL:GetText()
	return self.Label:GetText()
end

function PANEL:GetIcon()
	return self.Icon:GetImage()
end

function PANEL:CleanList()
	for k, panel in pairs(self.Items) do

		if not IsValid(panel) or panel:GetParent() ~= self.pnlCanvas then
			self.Items[k] = nil
		end
	end
end

function PANEL:Insert(pNode, pNodeNextTo, bBefore)
	pNode:SetParentNode(self)
	pNode:SetRoot(self:GetRoot())

	self:CreateChildNodes()

	if bBefore then
		self.ChildNodes:InsertBefore(pNodeNextTo, pNode)
	else
		self.ChildNodes:InsertAfter(pNodeNextTo, pNode)
	end

	self:InvalidateLayout()
end

function PANEL:LeaveTree(pnl)
	self.ChildNodes:RemoveItem(pnl, true)
	self:InvalidateLayout()
end


function PANEL:OnModified()
end

function PANEL:GetChildNode(iNum)
	if not IsValid(self.ChildNodes)  then return end
	return self.ChildNodes:GetChild(iNum)
end

function PANEL:Paint(w, h)
	derma.SkinHook("Paint", "TreeNode", self, w, h)
end

function PANEL:Copy()
	local copy = vgui.Create("pac_dtree_node", self:GetParent())
	copy:SetText(self:GetText())
	copy:SetIcon(self:GetIcon())
	copy:SetRoot(self:GetRoot())
	copy:SetParentNode(self:GetParentNode())

	if self.ChildNodes then
		for k, v in pairs(self.ChildNodes:GetChildren()) do
			local childcopy = v:Copy()
			copy:InsertNode(childcopy)
		end
	end

	self:SetupCopy(copy)

	return copy
end

function PANEL:SetupCopy(copy)

end

if Entity(1):IsPlayer() and not PAC_RESTART and not VLL2_FILEDEF then
	pace.OpenEditor()
	pace.RefreshTree(true)
end
