--[[
-----------------\
| MAD STUDIO 2016 \
| PROJECT MPB2     \
--------------------\

06/18/16
"CharacterDesignClone"
Copies and applies character design onto a clean humanoid
--]]

local BodyPartNames = {
	"Head",
	"Torso",
	"Right Arm",
	"Left Arm",
	"Right Leg",
	"Left Leg",
}

local CopyProperties = {
	"Material",
	"Reflectance",
	"Transparency",
}

local SpecialParticles = {
	"Smoke",
	"Fire",
	"Sparkles",
	"ParticleEmitter",
}

local function ScanClearParticles(ch)
	for _, obj in pairs(ch:GetChildren()) do
		ScanClearParticles(obj)
		for _, pnm in pairs(SpecialParticles) do
			if obj:IsA(pnm) then
				obj:Destroy()
				break
			end
		end
	end
end

local function TransferParticles(part_from, part_to)
	for _, obj in pairs(part_from:GetChildren()) do
		for _, pnm in pairs(SpecialParticles) do
			if obj:IsA(pnm) then
				local new_p = obj:Clone()
				new_p.Parent = part_to
				break
			end
		end
	end
end

local function IsABodyPart(part_name)
	for _, name in pairs(BodyPartNames) do
		if name == part_name then
			return true
		end
	end
	return false
end

local AttPart = Instance.new("Part")
AttPart.TopSurface = 0
AttPart.BottomSurface = 0
AttPart.Size = Vector3.new(0.2, 0.2, 0.2)
AttPart.CanCollide = false

local function ClearCharacterDesign(character)
	for _, obj in pairs(character:GetChildren()) do
		if obj:IsA("CharacterAppearance") or obj:IsA("Accoutrement") or obj.Name == "HAT" then
			obj:Destroy()
		end
		if obj.Name == "Torso" then
			local r = obj:FindFirstChild("roblox")
			if r ~= nil then
				r:Destroy()
			end
		end
		if obj.Name == "Head" then
			for _, obj2 in pairs(obj:GetChildren()) do
				if obj2:IsA("DataModelMesh") or obj2:IsA("FaceInstance") then
					obj2:Destroy()
				end
			end
		end
	end
	ScanClearParticles(character)
end


local function DesignCharacter(character, CharModel)
	
	ClearCharacterDesign(character)
	
	local CharModelCH = CharModel:GetChildren()
	
	local AttachmentData = {
		--{mesh, mesh_part, att_part, offset, is_accessory}
	}
	local BodyAttachments = {
		--{body_part, att_name, offset}
	}
	--C0 = BodyAttachment.CFrame * AccessoryAttachment.CFrame:inverse()
	
	--Scan through CharModel elements
	for _, obj in pairs(CharModelCH) do
		
		--Copy "CharacterAppearance" class instances
		if obj:IsA("CharacterAppearance") then
			local new_obj = obj:Clone()
			new_obj.Parent = character
		end
		
		--Body parts
		if obj:IsA("BasePart") and IsABodyPart(obj.Name) then
			local char_part = character:FindFirstChild(obj.Name)
			if char_part ~= nil then
				
				--Set transparency and reflectance
				for _, c_prop in pairs(CopyProperties) do
					char_part[c_prop] = obj[c_prop]
				end
				
				--Clone decals from head
				if obj.Name == "Head" then
					for _, obj_dec in pairs(obj:GetChildren()) do
						if obj_dec:IsA("FaceInstance") or obj_dec:IsA("DataModelMesh") then
							local new_obj = obj_dec:Clone()
							new_obj.Parent = char_part
						end
					end
				end
				
				--Checking for attachments
				for _, att_obj in pairs(obj:GetChildren()) do
					if att_obj:IsA("Attachment") then
						table.insert(BodyAttachments, {obj.Name, att_obj.Name, att_obj.CFrame:inverse()})
					end
				end
				
				TransferParticles(obj, char_part)
				
			end
		end
		
		--Hats
		if obj:IsA("Hat") then
			local get_handle = obj:FindFirstChild("Handle")
			if get_handle ~= nil then
				local get_mesh
				for _, mesh_obj in pairs(get_handle:GetChildren()) do
					if mesh_obj:IsA("DataModelMesh") then
						get_mesh = mesh_obj
						break
					end
				end
				if get_mesh ~= nil then
					table.insert(AttachmentData, {get_mesh, get_handle, "Head", CFrame.new(0, -0.5, 0) * obj.AttachmentPoint, false})
				end
			end
		end
		
		--Accessories
		if obj:IsA("Accessory") then
			local get_handle = obj:FindFirstChild("Handle")
			if get_handle ~= nil then
				local get_mesh, get_attachment
				for _, att_obj in pairs(get_handle:GetChildren()) do
					if att_obj:IsA("DataModelMesh") then
						get_mesh = att_obj
					elseif att_obj:IsA("Attachment") then
						get_attachment = att_obj
					end
				end
				if get_mesh ~= nil and get_attachment ~= nil then
					table.insert(AttachmentData, {get_mesh, get_handle, get_attachment.Name, get_attachment.CFrame, true})
				elseif get_mesh ~= nil then
					table.insert(AttachmentData, {get_mesh, get_handle, "Head", CFrame.new(0, -0.5, 0) * obj.AttachmentPoint, false})
				end
			end
		end
		
	end
	
	--Creating Accessories
	for _, att_dat in pairs(AttachmentData) do
		local attach_cf, attach_part
		
		if not att_dat[5] then --Hat type
			attach_cf = att_dat[4]
			attach_part = character:FindFirstChild("Head")
		else --Accessory type
			for _, body_att in pairs(BodyAttachments) do
				if body_att[2] == att_dat[3] then
					attach_cf = att_dat[4] * body_att[3]
					attach_part = character:FindFirstChild(body_att[1])
					break
				end
			end
		end
		
		if attach_cf ~= nil and attach_part ~= nil then
			local new_att = AttPart:Clone()
			new_att.Size = att_dat[2].Size
			new_att.Name = "HAT"
			for _, c_prop in pairs(CopyProperties) do --cloning handle part properties
				new_att[c_prop] = att_dat[2][c_prop]
			end
			TransferParticles(att_dat[2], new_att)
			local new_mesh = att_dat[1]:Clone()
			new_mesh.Parent = new_att
			local new_weld = Instance.new("Motor6D")
			new_weld.Name = "AttachementWeld"
			new_weld.Part0 = attach_part
			new_weld.Part1 = new_att
			new_weld.C1 = attach_cf
			new_att.Parent = character
			new_weld.Parent = attach_part
		end
	end
	
end

return DesignCharacter