selfcare.effect = {}

local random = math.random

local function sparkles(player, minsiz, maxsiz, loc)
    local pos = player:get_pos()
    local e_h = player:get_properties().eye_height
    local eye
    if not loc then loc = "body" end

if loc == "body" then
    eye = e_h - 0.45
end
        
      minetest.add_particlespawner({
	pos = {x = pos.x, y = pos.y + eye, z = pos.z},
	time = 0.1,
	amount = 4,
	vel = {min = {x = -0.3, y = -0.2, z = -0.3}, max = {x = 0.3, y = -0.4, z = 0.3}},
	acc = {min = {x = -0.1, y = 0.3, z = -0.1}, max = {x = 0.1, y = 0.4, z = 0.1}},
	size = {min = minsiz, max = maxsiz},
	texture = "selfcare_sparkles.png^[brighten:100",
	collisiondetection = true,
	minexptime = 1,
	maxexptime = 1.7
})
end

local function stray_bubble(player, height, exp)
    local pos = player:get_pos()
    local dir = player:get_look_dir()
    local eye = player:get_properties().eye_height - height

      minetest.add_particlespawner({
	pos = {x = pos.x + dir.x * 0.1, y = pos.y + eye, z = pos.z + dir.z * 0.1},
	time = 0.1,
	amount = 2,
	vel = {min = {x = -0.15, y = 0.15, z = -0.15}, max = {x = 0.15, y = -0.15, z = 0.15}},
	size = {min = 1, max = 2},
	texture = "selfcare_stray_bubble.png",
	collisiondetection = true,
	collision_removal = true,
	minexptime = exp - 0.5,
	maxexptime = exp + 0.5
})
end


local function WashBody(player, ver)
    local pos = player:get_pos()
    local dir = player:get_look_dir()
        
    local _vel
    local _acc
    local _miex
    local _maex
    local _sbex
    local _under_eye

if not ver or ver == nil then ver = "foaming" end

if ver == "foaming" then
    _vel = {min = {x = -0.19, y = 0.25, z = -0.19}, max = {x = 0.19, y = -0.25, z = 0.19}}
    _acc = {x = 0, y = 0, z = 0}
    _miex = 2.5
    _maex = 3.7
    _sbex = 4.2
    _under_eye = 0.7
elseif ver == "rinsing" then
    _vel = {min = {x = -0.45, y = 0.2, z = -0.45}, max = {x = 0.45, y = 0.3, z = 0.45}}
    _acc = {x = 0, y = -1.7, z = 0}
    _miex = 1.3
    _maex = 2
    _sbex = 2.5
    _under_eye = 0.3
end

    local eye = player:get_properties().eye_height - _under_eye

	stray_bubble(player, math.random(0.3, 0.7), _sbex)
      minetest.add_particlespawner({
	pos = {x = pos.x + dir.x * 0.05, y = pos.y + eye, z = pos.z + dir.z * 0.1},
	time = 0.1,
	amount = 6,
	vel = _vel,
	acc = _acc,
	size = {min = 3, max = 4},
	texture = "selfcare_bubble.png",
	collisiondetection = true,
	minexptime = _miex,
	maxexptime = _maex,
})
end

local function BubbleBomb(player, hex)
    local pos = player:get_pos()
    local dir = player:get_look_dir()
        
    local _vel
    local _acc
    local _miex
    local _maex
    local _sbex
    local _under_eye
    local v = random(1,2)
    local hex_t = {}

    if hex == "#AED7A1" then
	hex_t = {"#AED7A1", "#FED1D1"}
    else
	hex_t = {hex}
    end


if v == 1 then
    _vel = {min = {x = -0.19, y = 0.25, z = -0.19}, max = {x = 0.19, y = -0.25, z = 0.19}}
    _acc = {x = 0, y = 0, z = 0}
    _miex = 2.5
    _maex = 3.7
    _sbex = 4.2
    _under_eye = 0.7
elseif v == 2 then
    _vel = {min = {x = -0.45, y = 0.2, z = -0.45}, max = {x = 0.45, y = 0.3, z = 0.45}}
    _acc = {x = 0, y = -0.8, z = 0}
    _miex = 1.3
    _maex = 3
    _sbex = 3.5
    _under_eye = 0.3
end



    local texs = {"selfcare_bubble.png", "selfcare_bubble.png^(selfcare_bubble.png^[multiply:"..hex_t[random(#hex_t)]..")"}

    local eye = player:get_properties().eye_height - _under_eye

	stray_bubble(player, math.random(0.3, 0.7), _sbex)
      minetest.add_particlespawner({
	pos = {x = pos.x + dir.x * 0.05, y = pos.y + eye, z = pos.z + dir.z * 0.1},
	time = 0.1,
	amount = 15,
	vel = _vel,
	acc = _acc,
	size = {min = 3, max = 4},
	texture = texs[random(#texs)],
	collisiondetection = true,
	minexptime = _miex,
	maxexptime = _maex,
})

      minetest.add_particlespawner({
	pos = {x = pos.x, y = pos.y + eye, z = pos.z},
	time = 0.1,
	amount = 2,
	vel = {min = {x = -0.1, y = 0.1, z = -0.1}, max = {x = 0.2, y = 0.2, z = 0.2}},
	size = {min = 6, max = 7},
	texture = "selfcare_spray.png^[opacity:50",
	collisiondetection = true,
	minexptime = 5,
	maxexptime = 7
})
end

local function WashHair(player, hex)
    local pos = player:get_pos()
    local eye = player:get_properties().eye_height + 0.33

    local textures = {"selfcare_bubble.png", "selfcare_stray_bubble.png^(selfcare_stray_bubble.png^[multiply:"..hex.."^[opacity:230)"}
        
      minetest.add_particlespawner({
	pos = {x = pos.x, y = pos.y + eye, z = pos.z},
	time = 0.1,
	amount = 5,
	vel = {min = {x = -0.7, y = 0.3, z = -0.7}, max = {x = 0.7, y = 0.55, z = 0.7}},
	acc = {x = 0, y = -2, z = 0},
	size = {min = 2, max = 3},
	texture = textures[math.random(2)],
	collisiondetection = true,
	minexptime = 0.4,
	maxexptime = 0.6
})
end

local function CondishHair(player, typ)
    local pos = player:get_pos()
    local eye = player:get_properties().eye_height + 0.33
    local textures = {tx = "selfcare_cream.png"}

if typ == "gel" then
    textures.tx = "selfcare_light_cream.png"
end
        
      minetest.add_particlespawner({
	pos = {x = pos.x, y = pos.y + eye, z = pos.z},
	time = 0.1,
	amount = 5,
	vel = {min = {x = -0.7, y = 0.3, z = -0.7}, max = {x = 0.7, y = 0.55, z = 0.7}},
	acc = {x = 0, y = -2, z = 0},
	size = {min = 2, max = 3},
	texture = textures.tx,
	collisiondetection = true,
	minexptime = 0.4,
	maxexptime = 0.6
})
end

local function BrushTeeth(player)
    local pos = player:get_pos()
    local dir = player:get_look_dir()
    local eye = player:get_properties().eye_height - 0.1
        
      minetest.add_particlespawner({
	pos = {x = pos.x + dir.x * 0.2, y = pos.y + eye, z = pos.z + dir.z * 0.3},
	time = 0.1,
	amount = 25,
	vel = {min = {x = -0.2, y = 0.4, z = -0.2}, max = {x = 0.2, y = 0.4, z = 0.2}},
	acc = {x = 0, y = -1, z = 0},
	size = {min = 1, max = 1.5},
	texture = "selfcare_bubble.png^[multiply:#c8eced",
	collisiondetection = true,
	minexptime = 0.3,
	maxexptime = 0.5
})
end
local function ScrapeTongue(player, hex)
    local pos = player:get_pos()
    local dir = player:get_look_dir()
    local eye = player:get_properties().eye_height - 0.1

      minetest.add_particlespawner({
	pos = {x = pos.x + dir.x * 0.1, y = pos.y + eye, z = pos.z + dir.z * 0.21},
	time = 0.1,
	amount = 10,
	vel = {min = {x = -0.2, y = 0, z = -0.2}, max = {x = 0.2, y = 0, z = 0.2}},
	acc = {x = 0, y = 0, z = 0},
	size = {min = 1, max = 1},
	texture = "selfcare_cream.png^[multiply:"..hex,
	collisiondetection = true,
	minexptime = 0.2,
	maxexptime = 0.4
})
end

local washface_txt = {"selfcare_bubble.png", "selfcare_bubble.png^[multiply:#fff4ed"}

local function WashFace(player)
    local pos = player:get_pos()
    local dir = player:get_look_dir()
    local eye = player:get_properties().eye_height + 0.14
        
      minetest.add_particlespawner({
	pos = {x = pos.x + dir.x * 0.1, y = pos.y + eye, z = pos.z + dir.z * 0.2},
	time = 0.1,
	amount = 5,
	vel = {min = {x = -0.2, y = -0.4, z = -0.2}, max = {x = 0.2, y = -0.5, z = 0.2}},
	acc = {x = 0, y = 0.5, z = 0},
	size = {min = 1, max = 1.5},
	texture = washface_txt[random(#washface_txt)],
	collisiondetection = true,
	minexptime = 1,
	maxexptime = 1.5
})
end

local function Perfume(player, tint)
    local pos = player:get_pos()
    local dir = player:get_look_dir()
    local eye = player:get_properties().eye_height - 0.6
        
      minetest.add_particlespawner({
	pos = {x = pos.x, y = pos.y + eye, z = pos.z},
	time = 0.1,
	amount = 15,
	vel = {min = {x = -0.2, y = 0.2, z = -0.2}, max = {x = 0.2, y = 0.3, z = 0.2}},
	acc = {min = {x = -0.1, y = -0.2, z = -0.1}, max = {x = 0.1, y = -0.3, z = 0.1}},
	size = {min = 7, max = 10},
	texture = "selfcare_spray.png^[multiply:"..tint.."^[opacity:50",
	collisiondetection = false,
	minexptime = 1.5,
	maxexptime = 3
})
end

local function OilPlayer(player, focus)
    local pos = player:get_pos()
    local dir = player:get_look_dir()
    local e_h = player:get_properties().eye_height

if not focus then minetest.chat_send_player(player:get_player_name(), "error") return end

    if focus == "body" then
    local eye = e_h - 0.6
        
      minetest.add_particlespawner({
	pos = {x = pos.x, y = pos.y + eye, z = pos.z},
	time = 0.1,
	amount = 15,
	vel = {min = {x = -0.2, y = 0.2, z = -0.2}, max = {x = 0.2, y = 0.3, z = 0.2}},
	acc = {min = {x = -0.1, y = -0.2, z = -0.1}, max = {x = 0.1, y = -0.3, z = 0.1}},
	size = {min = 7, max = 10},
	texture = "selfcare_spray.png^[multiply:#DBA77D^[opacity:50",
	collisiondetection = false,
	minexptime = 1.5,
	maxexptime = 3
})
    end
end


local function effect(player, type, height, min_size, max_size, min_exp, max_exp, hex)
    local pos = player:get_pos()
    local offs = player:get_properties().eye_height + height

    local cream_tex
    local spray_tex

if hex then
    cream_tex = "selfcare_cream.png^(selfcare_cream.png^[opacity:170^[multiply:"..hex..")"
    spray_tex = "(selfcare_spray.png^[opacity:200)^[multiply:"..hex
else
    cream_tex = "selfcare_cream.png^[opacity:200"
    spray_tex = "selfcare_spray.png^[opacity:200"
end

	if type == "cream" then
        
      minetest.add_particlespawner({
	pos = {x = pos.x, y = pos.y + offs, z = pos.z},
	time = 0.1,
	amount = 7,
	vel = {min = {x = -0.7, y = 0.8, z = -0.7}, max = {x = 0.7, y = 1.2, z = 0.7}},
	acc = {x = 0, y = -4, z = 0},
	size = {min = min_size, max = max_size},
	texture = cream_tex,
	collisiondetection = true,
	minexptime = min_exp,
	maxexptime = max_exp
})
	elseif type == "spray" then
        
      minetest.add_particlespawner({
	pos = {x = pos.x, y = pos.y + offs, z = pos.z},
	time = 0.1,
	amount = 11,
	vel = {min = {x = -0.7, y = 0.8, z = -0.7}, max = {x = 0.7, y = 1.2, z = 0.7}},
	acc = {x = 0, y = -4.8, z = 0},
	size = {min = min_size, max = max_size},
	texture = spray_tex,
	collisiondetection = true,
	minexptime = mix_exp,
	maxexptime = max_exp
})
	end
end

function selfcare.effect.WashBody(user, c, ver)
    if c > 0 then
        WashBody(user, ver)
        
        minetest.after(0.05, function()
            selfcare.effect.WashBody(user, c - 1, ver)
        end)
	selfcare.set(user, "smell_t", "0")
	selfcare.set(user, "smell", "clean")
	selfcare.set(user, "perfume_t", "0")
	selfcare.set(user, "perfume", "aren't")
    end
    if c == 0 then
        minetest.after(1.3, function()
	    sparkles(user, 1.5, 2, "body")
	end)
        minetest.after(2, function()
	    sparkles(user, 0.6, 1.2, "body")
	end)
    end

	local bdr = selfcare.get(user, "b_dryness")
	local bdi = selfcare.get(user, "b_dirtiness")

	-- if the layer of dead skin cells is thin then it can be washed away with soap
	-- but flaky skin would make it hard to remove, and might damage skin so

	if (bdr == "smooth" or bdr == "soft" or bdr == "normal") and
	(bdi == "neutral" or bdi == "slightly unclean") then
	    selfcare.set(user, "b_dirtiness", "clean")
	end
end

function selfcare.effect.BubbleBomb(user, c, clr)
    if c > 0 then
        BubbleBomb(user, clr)
        
        minetest.after(0.05, function()
            selfcare.effect.BubbleBomb(user, c - 1, clr)
        end)
	selfcare.set(user, "smell_t", "0")
	selfcare.set(user, "smell", "clean")
	selfcare.set(user, "perfume_t", "0")
	selfcare.set(user, "perfume", "aren't")
    end
    if c == 0 then
        minetest.after(1.3, function()
	    sparkles(user, 2, 2.5, "body")
	end)
        minetest.after(2, function()
	    sparkles(user, 1, 2, "body")
	end)
    end

	local bdr = selfcare.get(user, "b_dryness")
	local bdi = selfcare.get(user, "b_dirtiness")
	local s = selfcare.get(user, "smell")

	-- if the layer of dead skin cells is thin then it can be washed away with soap
	-- but flaky skin would make it hard to remove, and might damage skin so

	if (bdr == "smooth" or bdr == "soft" or bdr == "normal") and
	(bdi == "neutral" or bdi == "slightly unclean") and (s ~= "bad") then
	    selfcare.set(user, "b_dirtiness", "clean")
	end
end

function selfcare.effect.CondishHair(user, c)
    local hair_condition = selfcare.get(user, "condish")
    local dirt = selfcare.get(user, "hair")

    if c > 0 then
        CondishHair(user, "condish")
        
        minetest.after(0.2, function()
            selfcare.effect.CondishHair(user, c - 1)
        end)
    end

	if hair_condition ~= "dehydrated" and dirt ~= "dirty" then
	  selfcare.set(user, "condish", "soft")
	  selfcare.set(user, "condish_t", "0")
	end

end

function selfcare.effect.GelHair(user, c)
    local hair_condition = selfcare.get(user, "condish")
    local dirt = selfcare.get(user, "hair")

    if c > 0 then
        CondishHair(user, "gel")
        
        minetest.after(0.2, function()
            selfcare.effect.GelHair(user, c - 1)
        end)
    end

	if hair_condition ~= "dehydrated" and dirt ~= "dirty" then
	  selfcare.set(user, "condish", "soft")
	  selfcare.set(user, "condish_t", "0")
	end

end

function selfcare.effect.MaskHair(user, c, clr)
    local hair_condition = selfcare.get(user, "condish")

    if c > 0 then
	for i = 1, 3 do
        effect(user, "cream", 0.3, 2, 3, 0.3, 0.4)
        effect(user, "cream", 0.3, 1.5, 2.5, 0.4, 0.6, clr)
        CondishHair(user, "gel")
	end
        
        minetest.after(0.2, function()
            selfcare.effect.MaskHair(user, c - 1, clr)
        end)
    end
	  selfcare.set(user, "condish", "soft")
	  selfcare.set(user, "condish_t", "0")
end


function selfcare.effect.WashHair(user, c, clr)
    if c > 0 then
        WashHair(user, clr)
        
        minetest.after(0.05, function()
            selfcare.effect.WashHair(user, c - 1, clr)
        end)
    end
	selfcare.set(user, "hair_t", "0")
	selfcare.set(user, "hair", "clean")
end

function selfcare.effect.BrushTeeth(user, c)
    if c > 0 then
        BrushTeeth(user)
        
        minetest.after(0.2, function()
            selfcare.effect.BrushTeeth(user, c - 1)
        end)
    end
	selfcare.set(user, "teeth_t", "0")
	selfcare.set(user, "breath_t", "0")
	selfcare.set(user, "breath", "minty")
	selfcare.set(user, "breath_t", "0")
end

function selfcare.effect.WashFace(user, c)
    local _f = selfcare.get(user, "_faceskin")
    local s = selfcare.get(user, "skin_type")

    if c > 0 then
        WashFace(user)
        
        minetest.after(0.05, function()
            selfcare.effect.WashFace(user, c - 1)
        end)
    end
	selfcare.set(user, "faceskin", "clean")
	selfcare.set(user, "faceskin_t", "0")

	if s ~= "oily" and _f == "oily" then
	  selfcare.set(user, "_faceskin", "dry")
	elseif s == "oily" and _f == "oily" then
	  selfcare.set(user, "_faceskin", "soft")
	elseif s == "oily" and _f == "soft" then
	  selfcare.set(user, "_faceskin", "dry")
	end
end

function selfcare.effect.Perfume(user, c, tint)
    if c > 0 then
        Perfume(user, tint)
        
        minetest.after(0.2, function()
            selfcare.effect.Perfume(user, c - 1, tint)
        end)
    end
	selfcare.set(user, "perfume", "are")
	selfcare.set(user, "perfume_t", "0")
end

function selfcare.effect.OilPlayer(user, c, focus)
    if c > 0 then
        OilPlayer(user, focus)
	sparkles(user, 0.7, 1, "body")
        
        minetest.after(0.2, function()
            selfcare.effect.OilPlayer(user, c - 1, focus)
        end)
    end
end

local function CreamFace(player)
    local pos = player:get_pos()
    local dir = player:get_look_dir()
    local eye = player:get_properties().eye_height + 0.14
        
      minetest.add_particlespawner({
	pos = {x = pos.x + dir.x * 0.1, y = pos.y + eye, z = pos.z + dir.z * 0.2},
	time = 0.1,
	amount = 5,
	vel = {min = {x = -0.2, y = -0.4, z = -0.2}, max = {x = 0.2, y = -0.5, z = 0.2}},
	acc = {x = 0, y = 0.5, z = 0},
	size = {min = 1, max = 1.5},
	texture = "selfcare_light_cream.png^[opacity:234",
	collisiondetection = true,
	minexptime = 1,
	maxexptime = 1.5
})
        
      minetest.add_particlespawner({
	pos = {x = pos.x + dir.x * 0.1, y = pos.y + eye, z = pos.z + dir.z * 0.2},
	time = 0.1,
	amount = 5,
	vel = {min = {x = -0.2, y = -0.4, z = -0.2}, max = {x = 0.2, y = -0.5, z = 0.2}},
	acc = {x = 0, y = 0.5, z = 0},
	size = {min = 2, max = 2},
	texture = "selfcare_spray.png^[opacity:170",
	collisiondetection = true,
	minexptime = 1,
	maxexptime = 1.5
})
end

local function BodyLotion(player)
    local pos = player:get_pos()
    local dir = player:get_look_dir()
    local eye = player:get_properties().eye_height - 0.47
        
      minetest.add_particlespawner({
	pos = {x = pos.x, y = pos.y + eye, z = pos.z},
	time = 0.1,
	amount = 6,
	vel = {min = {x = -0.3, y = 0.4, z = -0.3}, max = {x = 0.3, y = 0.4, z = 0.3}},
	acc = {min = {x = -0.1, y = -0.9, z = -0.1}, max = {x = 0.1, y = -0.9, z = 0.1}},
	size = {min = 7, max = 9},
	texture = "selfcare_spray.png^[opacity:120",
	collisiondetection = true,
	minexptime = 1,
	maxexptime = 1.7
})
end

local function BodyScrub(player, hex)
    local pos = player:get_pos()
    local eye = player:get_properties().eye_height - 0.7
        
      minetest.add_particlespawner({
	pos = {x = pos.x, y = pos.y + eye, z = pos.z},
	time = 0.1,
	amount = 15,
	vel = {min = {x = -0.19, y = 0.25, z = -0.19}, max = {x = 0.19, y = -0.25, z = 0.19}},
	size = {min = 3, max = 4},
	texture = "selfcare_scrub.png^[multiply:"..hex,
	collisiondetection = true,
	minexptime = 2,
	maxexptime = 2.7
})
end

function selfcare.effect.CreamFace(user, c)
    local f = selfcare.get(user, "faceskin")
    local s = selfcare.get(user, "skin_type")

    if c > 0 then
        CreamFace(user)
        
        minetest.after(0.2, function()
            selfcare.effect.CreamFace(user, c - 1)
        end)	   
    end
	selfcare.set(user, "_faceskin", "soft")
	selfcare.set(user, "_faceskin_t", "0")

	if f == "dirty" then
	    if s == "oily" then
		if random(1,2) < 2 then
		end
	    elseif s == "normal" then
		if random(1,4) < 2 then
		    selfcare.set(user, "faceskin", "clogged")
		    selfcare.set(user, "_faceskin", "oily")
	    elseif s == "dry" then
		return end
	    end
	end
end

function selfcare.effect.FlossTeeth(user)
    local t = selfcare.get(user, "_teeth")

	if t == "a plaque colony" then -- must pass it multiple times to clean properly ;)
	  selfcare.set(user, "_teeth", "plaque")
	elseif t == "plaque" then
	  selfcare.set(user, "_teeth", "build-up")
	elseif t == "build-up" then
	  selfcare.set(user, "_teeth", "some dirt")
	elseif t == "some dirt" then
	  selfcare.set(user, "_teeth", "nothing")
	  minetest.chat_send_player(user:get_player_name(), "no plaque between my teeth!")
	end
    selfcare.set(user, "_teeth_t", "0")
end

function selfcare.effect.BodyLotion(user, c)
    local d = selfcare.get(user, "b_dryness")

    if c > 0 then
        BodyLotion(user)
        
        minetest.after(0.2, function()
            selfcare.effect.BodyLotion(user, c - 1)
        end)
    end

	if d == "flaky" or d == "slightly flaky" then
	    selfcare.set(user, "b_dryness", "slightly dry")
	elseif d == "slightly dry" or d == "normal" or d == "soft" then
	    selfcare.set(user, "b_dryness", "smooth")
	end
    selfcare.set(user, "b_dryness_t", "0")
end

function selfcare.effect.BodyScrub(user, c, clr)
    local d = selfcare.get(user, "b_dirtiness")
    local s = selfcare.get(user, "smell") == "clean"

    if c > 0 then
        BodyScrub(user, clr)
        
        minetest.after(0.2, function()
            selfcare.effect.BodyScrub(user, c - 1, clr)
        end)
    end

	if d == "grimy" or d == "dirty" then
	  if s then
	    selfcare.set(user, "b_dirtiness", "slightly unclean")
	  elseif not s then
	    selfcare.set(user, "b_dirtiness", "slightly dirty")
	  end
	elseif d == "slightly dirty" or d == "slightly unclean"  then
	  if s then
	    selfcare.set(user, "b_dirtiness", "clean")
	  elseif not s then
	    selfcare.set(user, "b_dirtiness", "neutral")
	  end
	elseif d == "neutral" then
	  selfcare.set(user, "b_dirtiness", "clean")
	end
    selfcare.set(user, "b_dirtiness_t", "0")
end

function selfcare.effect.ScrapeTongue(user, c)
    local t = selfcare.get(user, "tongue")
    local br = selfcare.get(user, "breath")
    local hex = "#FFE0EA"

if t == "pink" then hex = "#FFE0EA"
elseif t == "peach" then hex = "#FFDCCE"
elseif t == "yellow" then hex = "#FFE9B6"
else return
end

    if c > 0 then
        ScrapeTongue(user, hex)
        
        minetest.after(0.2, function()
            selfcare.effect.ScrapeTongue(user, c - 1)
        end)
    end
	if br == "disgusting" or br == "bad" then
	    selfcare.set(user, "breath", "slightly bad")
	end
	if t == "yellow" then
	    selfcare.set(user, "tongue", "peach")
	elseif t == "peach" then
	    selfcare.set(user, "tongue", "pink")
	end
end