--[[⠀
----------------------------------------------------------------------------------------------------------------------------⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀                       ⠀⢀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣀⣀⣀⣀⣀⣀⣰⣦⣀⣀⠀⠠⠄⠄⠠⠀⠀⢀⣠⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⡏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣶⡿⢿⣦⠀⠀⠀⠀⠀⠀⠀⢀⡷⠀⠀⠀⠀⠀⣀⠀⠀⠀⠀⠀⣩⡿⠋⠙⠉⢩⡿⠟⠀⠀⠀⠀⠀⠀⢀⣶⣾⠟⠋⠛⣿⣷⡄⠀⠀⠀⠀⠀⣴⣿⠂⠀⠀⣼⡿⠀⠀⠀⠀⠀⠀⢀⣠⡴⠶⣤⠀⠀⠀⠀⠀⠀⠀⠀⣠⣴⠦⠤⣤⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⢀⣼⡿⠋⠀⢸⠏⠀⠀⠀⠀⠀⠀⠀⣼⠃⠀⠀⠀⠀⢠⡇⠀⠀⠀⢠⣾⠋⠀⠀⠀⠀⣸⠀⠀⠀⠀⠀⠀⠀⢠⣿⠋⠀⠀⠀⠀⠛⠛⠁⠀⠀⠀⢀⣾⣿⠏⠀⠀⢀⡿⠃⠀⠀⠀⠀⠀⠶⠋⠁⢀⣰⠟⠀⠀⠀⠀⠀⠀⠀⣹⣿⠀⠀⠀⠀⣨⣿⠇⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⣾⡟⢀⣠⣤⣴⣶⠆⠀⠀⠀⠀⠀⢰⠃⠀⠀⠀⠀⠀⣾⠀⠀⠀⣰⣿⠃⠀⠀⠀⠀⠀⣿⡀⠀⠀⠀⠀⠀⢀⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⠋⠀⠀⢀⡾⠁⠀⠀⠀⠀⠀⠀⠀⣠⣶⣯⣅⡀⠀⠀⠀⠀⠀⠀⠀⣿⡇⢀⣠⠴⠞⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⣸⡟⠀⠛⠉⣠⣾⠃⠀⠀⠀⠀⠀⠀⣼⠀⠀⠀⠀⠀⠀⢿⣤⡴⢺⢻⠃⠀⠀⠀⠀⠀⢸⡿⠁⠀⠀⠀⠀⠀⠀⢿⠀⠀⠀⠀⢀⣤⠀⠀⠀⠀⠀⢀⣿⣇⡤⠤⢤⣾⣤⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢻⡆⠀⠀⠀⠀⠀⣿⣯⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⣿⠃⠀⠀⢀⣼⠇⠀⠀⠀⠀⠀⠀⣰⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⢂⠇⠀⠀⠀⠀⠀⠀⣾⡅⠀⠀⠀⠀⠀⠀⠀⢸⣧⡀⠀⠀⣼⠇⠀⠀⠀⠀⠀⢸⣿⠀⠀⠀⠐⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⠃⠀⠀⠀⠀⠀⢰⡏⠘⣦⠀⠀⠀⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠘⢧⣤⡶⠟⢻⠀⠀⠀⠀⠀⠀⢠⡏⠀⠀⠀⠀⠀⠀⠀⠀⠀⢘⠏⠀⠀⠀⠀⠀⠀⢰⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠙⠿⣶⡾⠋⠀⠀⠀⠀⠀⠀⢸⡟⠀⠀⠀⢰⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⠞⠁⠀⠀⠀⠀⠀⠀⠁⠀⠈⠙⠂⠔⠊⠁⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⠀⠀⠀⠀⠀⢀⣿⣤⠶⠒⠒⠁⠀⠀⠀⠀⢠⠏⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⠀⠀⠀⠄⠐⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀

----------------------------------------------------------------------------------------------------------------------------
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
Please contact me if you need to hire someone to do mods or other design related tasks
https://steamcommunity.com/id/glytch3r/myworkshopfiles/
https://www.glytch3r.com
https://ko-fi.com/glytch3r
Discord: Glytch3r#2892

----------------------------------------------------------------------------------------------------------------------------
--]]
require "recipecode"


Recipe = Recipe or {}
Recipe.GetItemTypes = Recipe.GetItemTypes or {}
Recipe.OnCanPerform = Recipe.OnCanPerform or {}
Recipe.OnCreate = Recipe.OnCreate or {}
Recipe.OnGiveXP = Recipe.OnGiveXP or {}
Recipe.OnTest = Recipe.OnTest or {}

local function dakiBuffEffect()
	
	local item = nil
	local player = getPlayer()

	--just type the Profession on the "" and remove the -- on the left side of the line below
	if player then
    	local descriptor = player:getDescriptor()
   	 	if descriptor then
        	local profession = descriptor:getProfession()
        	if profession then
            	local professionIsWeeb = profession == "Weeb"
            	if not professionIsWeeb then return end
        	else
            	return
        	end
    	else
        	return
    	end
	else
    	return
	end

	-- just type the trait on the "" and remove the -- on the left side of the line below
	--if not player:HasTrait("") then return end

	--check if servers  SleepAllowed is on
	--[[if getServerOptions():getBoolean("SleepAllowed") then
		-- somewhat counters sleepless traits effect by adding more fatigue but only uptil 0.8
		if player and (player:HasTrait("NightOwl") or player:HasTrait("NeedsLessSleep") or player:HasTrait("Insomniac")) and player:getStats():getFatigue() <= 0.8 then
			player:getStats():setFatigue(player:getStats():getFatigue() + 0.01)
		end
		--  same as above but without the limit
		if player:HasTrait("NeedsMoreSleep") then
			player:getStats():setFatigue(player:getStats():getFatigue() + 0.01)
		end
	end]]
	
	--player:getModData()['BuffEffect'] = "daki not found" -- for testing
	if player:getInventory():getFirstEvalRecurse(function(item)			
			return item:hasTag("DakiWeapon") or item:hasTag("DakiArmorFront") or item:hasTag("DakiArmorBack")
		end) then
		--player:getModData()['BuffEffect'] = "daki found" -- for testing
		local bodyDamage = player:getBodyDamage()
		local stats = player:getStats()

		bodyDamage:setUnhappynessLevel(bodyDamage:getUnhappynessLevel() - (bodyDamage:getUnhappynessLevel() / 4))
		if bodyDamage:getUnhappynessLevel() < 0 then
			bodyDamage:setUnhappynessLevel(0);
		end
		if player:isAsleep() then
			stats:setStress(stats:getStress() - (stats:getStress() / 4))
			if stats:getStress() < 0 then
				stats:setStress(0);
			end
		end
		-- else  player:getModData()['BuffEffect'] = "something might be wrong" -- for testing
	end
	--player:Say(player:getModData()['BuffEffect']) -- for testing
end

Events.EveryTenMinutes.Add(dakiBuffEffect)

local bodyParts = {
	BloodBodyPartType.Back,
	BloodBodyPartType.Foot_L,
	BloodBodyPartType.Foot_R,
	BloodBodyPartType.ForeArm_L,
	BloodBodyPartType.ForeArm_R,
	BloodBodyPartType.Groin,
	BloodBodyPartType.Hand_L,
	BloodBodyPartType.Hand_R,
	BloodBodyPartType.Head,
	BloodBodyPartType.LowerLeg_L,
	BloodBodyPartType.LowerLeg_R,
	BloodBodyPartType.Neck,
	BloodBodyPartType.Torso_Lower,
	BloodBodyPartType.Torso_Upper,
	BloodBodyPartType.UpperArm_L,
	BloodBodyPartType.UpperArm_R,
	BloodBodyPartType.UpperLeg_L,
	BloodBodyPartType.UpperLeg_R
}

local function transferData(old,new)
	new:copyModData(old:getModData())
end

local function dataFromClothing(clothingItem,result)
	local clothing = result:getModData()

	local visual = clothingItem:getVisual()
	for i , v in ipairs(bodyParts) do
		local part = {}
		part.dirt = visual:getDirt(v)
		part.blood = visual:getBlood(v)
		part.hasHole = visual:getHole(v) ~= 0

		local patch = clothingItem:getPatchType(v)
		if patch then
			local tempTable = {}
			tempTable['biteDefense'] = patch:getBiteDefense()
			tempTable['fabricTypeName'] = patch:getFabricTypeName()
			tempTable['scratchDefense'] = patch:getScratchDefense()
			part.patch = tempTable
		else
			part.patch = nil
		end

		clothing[i] = part
	end

	clothing.dirtyness = clothingItem:getDirtyness()
	--clothing.bloodLevel = clothingItem:getBloodLevel()
end

local function dataToClothing(clothingItem, result, player)
	local clothing = clothingItem:getModData()
	if type(clothing[1]) ~= "table" then return end

	local visual = result:getVisual()
	for i , v in ipairs(bodyParts) do
		local part = clothing[i]
		visual:setDirt(v, part.dirt)
		visual:setBlood(v, part.blood)
		if part.hasHole then visual:setHole(v) end

		if part.patch then
			local fullType = 'Base.' .. string.gsub(part.patch.fabricTypeName, '%s+', '')
			local fabricItem = InventoryItemFactory.CreateItem(fullType)
			result:addPatch(player, v, fabricItem)
		end

		clothing[i] = nil
	end
	result:setDirtyness(clothing.dirtyness)
	--result:setBloodLevel(clothing.bloodLevel)
end

local function GetPatches(clothingItem)
	local patchesTable = {}
	for i , v in ipairs(bodyParts) do
		local patch = clothingItem:getPatchType(v)
		if patch then
			print("Found patch in index " .. tostring(v))
			local tempTable = {}
			tempTable["partIndex"] = i
			tempTable['biteDefense'] = patch:getBiteDefense()
			tempTable['fabricTypeName'] = patch:getFabricTypeName()
			tempTable['scratchDefense'] = patch:getScratchDefense()
			table.insert(patchesTable, tempTable)
		end
	end

	return patchesTable
end

local function SetPatches(patchesTable, player, newItem)
	for _, patch in ipairs(patchesTable) do
		print("Found table with" .. patch.fabricTypeName)
		local fullType = 'Base.' .. string.gsub(patch.fabricTypeName, '%s+', '')
		local fabricItem = InventoryItemFactory.CreateItem(fullType)
		newItem:addPatch(player, bodyParts[patch.partIndex], fabricItem)
	end
end


function Recipe.OnCreate.dakiCondition(items, result, player, selectedItem)



	--[[ 	if instanceof(result, "Clothing")  then
		if selectedItem:getModData()['prevDirtyness'] ~= nil then
			result:setDirtyness(selectedItem:getModData()['prevDirtyness'])
		end
	end ]]
	
	--TODO bug note:    ARMOR to WEAPON worked but turning WEAPON to ARMOR failed

	--TODO armor to weapon
	--TODO guns dont get dirty -- so if the result is a gun, Store armor dirtlevel to that gun 
	if instanceof(selectedItem, "Clothing") and instanceof(result, "HandWeapon") then	
		dataFromClothing(selectedItem,result)
		result:setBloodLevel(selectedItem:getBloodLevel() / 100 )

		--[[ prev
            result:getModData()['prevPatches'] = GetPatches(selectedItem)

            if selectedItem:getDirtyness() >= 0 then
                    result:getModData()['prevDirtyness'] = selectedItem:getDirtyness()
            end
            --]]

		--restore the rope when converting to weapon
		if instanceof(result, "HandWeapon") then
			local inv = getPlayer():getInventory()
			inv:AddItem("Base.Rope")
		end
	end
	--TODO weapon to armor
	--TODO guns dont get dirty -- so if the result is a armor Apply  the weapon  moddata  to the armor if there are data stored 
	if instanceof(selectedItem, "HandWeapon") and instanceof(result, "Clothing") then
		dataToClothing(selectedItem,result,player)
		result:setBloodLevel(selectedItem:getBloodLevel() * 100 )

		--[[ prev
		local prevPatches = selectedItem:getModData()['prevPatches']
		if prevPatches then
			SetPatches(prevPatches, player, result)
		end
		local prevDirtyness = selectedItem:getModData()['prevDirtyness']
		if prevDirtyness then
			result:setDirtyness(prevDirtyness)
		end
		--]]
	end
	
	------------------------   DBG         ---------------------------
	if isDebugEnabled() then 
		print('----------------------------------------------')
		if instanceof(result, "HandWeapon") then 
			print('weapon mode') ; getPlayer():Say('weapon mode') 
		elseif  instanceof(result, "Clothing") then 
			print('armor mode') ; getPlayer():Say('armor mode')  
		end
		if  instanceof(result, "Clothing") then	
			--result:setDirtyness(1)  --uncomment this to force add dirt when converting to armor only
			--result:setBloodLevel(1) --uncomment this to force add blood when converting to armor only
			print('result:getDirtyness '..result:getDirtyness()) 
		end
		--result:setBloodLevel(selectedItem:getBloodLevel() )--+ result:getBloodLevel())
		--print('result:getBloodLevel '..result:getBloodLevel())
		result:setCondition(selectedItem:getCondition())
		print('result:getCondition '..result:getCondition())		
		print('----------------------------------------------')
	else
		--transfer Blood and condition
		--local blood = selectedItem:getBloodLevel()
		--result:setBloodLevel(blood)
		local condition = selectedItem:getCondition()
		result:setCondition(condition)
		result:resetModelNextFrame()
	end 
end

	
	--TODO properties that applies for both weapon and armor
	--[[

	print(getPlayer():getPrimaryHandItem():hasBlood())  
	--print(getPlayer():getPrimaryHandItem():hasDirt()) 
	
	------------------------               ---------------------------
	--use this to test daki while equipped primary hand as weapon
	--print(getPlayer():getPrimaryHandItem():getDirtyness()) 
	print(getPlayer():getPrimaryHandItem():getBloodLevel()) 


	
	getPlayer():getPrimaryHandItem():setDirtyness(2) -- doesnt work cuz guns cant have dirt
	print(getPlayer():getPrimaryHandItem():getDirtyness()) 

	getPlayer():getPrimaryHandItem():setBloodLevel(1) 
	print(getPlayer():getPrimaryHandItem():getBloodLevel()) 
	
	------------------------               ---------------------------
	print(getPlayer():getPrimaryHandItem():getBloodLevel()) 
	print(getPlayer():getClothingItem_Back():getBloodLevel())
	print(getPlayer():getClothingItem_Back():getDirtyness()) 
	------------------------               ---------------------------
	--use this to test daki while equipped (back)  as armor
	print(getPlayer():getClothingItem_Back():getDirtyness()) 
	print(getPlayer():getClothingItem_Back():getBloodLevel()) 	
	
	getPlayer():getClothingItem_Back():setDirtyness(3)
	print(getPlayer():getClothingItem_Back():getDirtyness()) 
	
	getPlayer():getClothingItem_Back():setBloodLevel(2)
	print(getPlayer():getClothingItem_Back():getBloodLevel()) 
	------------------------               ---------------------------
	]]






--put this on the txt recipe script
--OnCreate:Recipe.OnCreate.dakiCondition,

--[[ function Recipe.OnCreate.dakiCondition(items, result, player)
	local item = nil
	local daki = nil


	for i = 0, items:size() - 1 do
		item = items:get(i)
		if isDaki(item) then
			if item and (instanceof(item, "Clothing") )then
				result:setDirtyness(item:getDirtyness())
				result:setBloodLevel(item:getBloodLevel())
			end
			daki = item
			break
		end
	end
	--if daki:isDirty() then result:setDirtyness(daki:getDirtyness()) end
	--if daki:isBloody() then result:setBloodLevel(daki:getBloodLevel()) end
	local RarmorFront = result:hasTag("DakiArmorFront")
	local SarmorFront = daki:hasTag("DakiArmorFront")
	local RarmorBack = result:hasTag("DakiArmorBack")
	local SarmorBack = daki:hasTag("DakiArmorBack")


	-- if the conversion is from armor to armor then dont do anything else
	if SarmorBack and RarmorFront then
		return
	elseif SarmorFront and RarmorBack then
		return
	end


	local cond = daki:getModData()['prevConditon']
	local toWeap = result:hasTag("DakiWeapon")
	local fromWeap = daki:hasTag("DakiWeapon")

	if toWeap then
		-- if the item doesnt have moddata then dont do anything else
		if not cond then
			return

			-- if the item has moddata then apply to the weapon
		elseif cond then
			result:setCondition(cond)
			-- TODO Carry over patches
			result:getModData()['prevPatches'] = GetPatches(daki)
		end

		-- if the item is a weapon then store the moddata to the armor
	elseif fromWeap and daki then
		result:getModData()['prevConditon'] = daki:getCondition()
		result:setCondition(daki:getCondition())

		if result:getModData()['prevPatches'] ~= nil then
			SetPatches(daki:getModData()['prevPatches'], player, result)
		end

		if not instanceof(result, "Clothing") then
			local inv = getPlayer():getInventory()
			inv:AddItem("Base.Rope")
		end
	end
end ]]

--[[ function Recipe.OnCreate.UndoArmor(items, result, player)
	local inv = getPlayer():getInventory()
	inv:AddItem("Base.Rope")
end
 ]]

function Recipe.OnCreate.DakiFlip(items, result, player, selectedItem, firstHand, secondHand)
    result:setCondition(selectedItem:getCondition());
    if secondHand or firstHand then
        if not player:getPrimaryHandItem() then
            player:setPrimaryHandItem(result);
        end
        player:setSecondaryHandItem(result);
    end
	transferData(selectedItem,result)
end

