--[[
BY
 _____   _____   __   _
|  _  \ /  _  \ |  \ | |
| | | | | | | | |   \| |
| | | | | | | | | |\   |
| |_| | | |_| | | | \  |
|_____/ \_____/ |_|  \_|

]]

local containers = require("containers")

local assets =
{
    Asset("ANIM", "anim/potions.zip"),
}


local ADD_HEALTH = 32
--local ADD_HEALING = -0.33
local ADD_FOOD = 40
local ADD_SANITY = 30

local PENALTY_SANITY_SMALL = -2
local PENALTY_SANITY = -5
local PENALTY_HUNGER_SMALL = -7
local PENALTY_HUNGER = -15
local PENALTY_HEALTH_SMALL = -5
local PENALTY_HEALTH = -15


local function create_luminosity_fx(eater, lightprefab)
    if eater.wormlight ~= nil then
        if eater.wormlight.prefab == lightprefab then
            eater.wormlight.components.spell.lifetime = 0
            eater.wormlight.components.spell:ResumeSpell()
            return
        else
            eater.wormlight.components.spell:OnFinish()
        end
    end

    local light = SpawnPrefab(lightprefab)
    light.components.spell:SetTarget(eater)
    if light:IsValid() then
        if light.components.spell.target == nil then
            light:Remove()
        else
            light.components.spell:StartSpell()
            light.fx.Light:SetColour(238/255, 255/255, 112/255)
        end
    end
end


local function onusepotioneffect(inst, eater)

	if eater.components.health ~= nil and eater.components.sanity ~= nil and eater.components.hunger ~= nil then
		if inst.potionpower == "strange" then --strange
			eater.components.sanity:DoDelta(PENALTY_SANITY*3)
			eater.components.hunger:DoDelta(PENALTY_HUNGER)
			eater.components.health:DoDelta(PENALTY_HEALTH)
			SpawnPrefab("donfx_dark_smoke").Transform:SetPosition(eater.Transform:GetWorldPosition())
		elseif inst.potionpower == "life" then --life
			eater.components.health:DoDelta(ADD_HEALTH)
			eater.components.hunger:DoDelta(PENALTY_HUNGER_SMALL)
			SpawnPrefab("donfx_red_smoke").Transform:SetPosition(eater.Transform:GetWorldPosition())
		elseif inst.potionpower == "food" then --food
			eater.components.hunger:DoDelta(ADD_FOOD)
			eater.components.sanity:DoDelta(PENALTY_SANITY)
			SpawnPrefab("donfx_orange_smoke").Transform:SetPosition(eater.Transform:GetWorldPosition())
		elseif inst.potionpower == "sanity" then --sanity
			eater.components.sanity:DoDelta(ADD_SANITY)
			eater.components.hunger:DoDelta(PENALTY_HUNGER)
			SpawnPrefab("donfx_cyan_smoke").Transform:SetPosition(eater.Transform:GetWorldPosition())
		elseif inst.potionpower == "light" then --sanity
			create_luminosity_fx(eater, "wormlight_light_lesser")
			eater.components.sanity:DoDelta(PENALTY_SANITY)
			SpawnPrefab("donfx_yellow_smoke").Transform:SetPosition(eater.Transform:GetWorldPosition())
		elseif inst.potionpower == "maxlife" then --max_life
			--eater.components.health:DeltaPenalty(ADD_HEALING)
      eater.components.health:DoDelta(ADD_HEALTH*10)
			eater.components.sanity:DoDelta(PENALTY_SANITY)
			eater.components.hunger:DoDelta(PENALTY_HUNGER)
			SpawnPrefab("donfx_pink_smoke").Transform:SetPosition(eater.Transform:GetWorldPosition())
		end
	end

end


local function OnProjectileDamage(inst, attacker, target)
	local range = 0
	local damage = 0

	if inst.potionpower == "poisonous" then
		SpawnPrefab("donfx_pink_smoke").Transform:SetPosition(inst.Transform:GetWorldPosition())
		SpawnPrefab("donfx_shadow_despawn_pink").Transform:SetPosition(inst.Transform:GetWorldPosition())
		range = 5
	end

	if inst.potionpower == "sleep" then
		SpawnPrefab("donfx_yellow_smoke").Transform:SetPosition(inst.Transform:GetWorldPosition())
		SpawnPrefab("donfx_shadow_despawn_yellow").Transform:SetPosition(inst.Transform:GetWorldPosition())
		range = 3.5
	end

	if range > 0 then
		local x, y, z = inst.Transform:GetWorldPosition()
		local ents = TheNet:GetPVPEnabled() and
		TheSim:FindEntities(x, y, z, range, nil, { "playerghost", "FX", "DECOR", "INLIMBO" }, { "sleeper", "player" }) or
		TheSim:FindEntities(x, y, z, range, { "sleeper" }, { "player", "FX", "DECOR", "INLIMBO" })

		for i, v in ipairs(ents) do
			if v ~= inst and not (v.components.freezable ~= nil and v.components.freezable:IsFrozen()) and
			not (v.components.pinnable ~= nil and v.components.pinnable:IsStuck()) then

				--print("Find: "..v.prefab)

				if inst.potionpower == "poisonous" then
					if v.components.combat ~= nil then
						damage = math.random(10) + math.random(10) + math.random(10) + math.random(15) + 15
						v.components.combat:GetAttacked(attacker, damage, nil)
						attacker.components.sanity:DoDelta(PENALTY_SANITY_SMALL)
					end
				end

				if inst.potionpower == "sleep" then
					local mount = v.components.rider ~= nil and v.components.rider:GetMount() or nil
                    if mount ~= nil then
                        mount:PushEvent("ridersleep", { sleepiness = 10, sleeptime = 20 })
                    end
                    if v.components.sleeper ~= nil then
                        v.components.sleeper:AddSleepiness(10, 20)
                    elseif v.components.grogginess ~= nil then
                        v.components.grogginess:AddGrogginess(10, 20)
                    else
                        v:PushEvent("knockedout")
                    end
					attacker.components.sanity:DoDelta(PENALTY_SANITY_SMALL)
				end

				SpawnPrefab("donfx_red_smoke").Transform:SetPosition(v.Transform:GetWorldPosition())
			end
		end
	end

	inst:Remove()
end
local function OnPotionThrown(inst)
    inst:AddTag("NOCLICK")
    inst.persists = false

    inst.Physics:SetMass(1)
    inst.Physics:SetCapsule(0.2, 0.2)
    inst.Physics:SetFriction(0)
    inst.Physics:SetDamping(0)
    inst.Physics:SetCollisionGroup(COLLISION.CHARACTERS)
    inst.Physics:ClearCollisionMask()
    inst.Physics:CollidesWith(COLLISION.WORLD)
    inst.Physics:CollidesWith(COLLISION.OBSTACLES)
    inst.Physics:CollidesWith(COLLISION.ITEMS)
end

local function MakeDonPotion(prefabname, anim, power, ptype, lightcolor)
	local function fn()
		local inst = CreateEntity()

		inst.entity:AddTransform()
		inst.entity:AddAnimState()
		inst.entity:AddLight()
		inst.entity:AddNetwork()

		inst.AnimState:SetBank("potions")
		inst.AnimState:SetBuild("potions")
		inst.AnimState:PlayAnimation(anim)

		MakeInventoryPhysics(inst)

		inst.entity:SetPristine()

		if not TheWorld.ismastersim then
			return inst
		end

	if power ~= "none" then

		local potionpower = power
		inst.potionpower = power

		if ptype == "eat" then
			inst:AddComponent("edible")
			inst.components.edible.oneaten = onusepotioneffect
			inst.components.edible.healthvalue = 0
			inst.components.edible.hungervalue = 0
			inst.components.edible.sanityvalue = 0
			inst.components.edible.foodtype = FOODTYPE.MEAT

			inst:AddComponent("perishable")
			inst.components.perishable:SetPerishTime(TUNING.PERISH_MED)
			inst.components.perishable:StartPerishing()
			inst.components.perishable.onperishreplacement = "donpotionstrange"
		elseif ptype == "projectile" then
		    inst:AddComponent("complexprojectile")
			inst.components.complexprojectile:SetHorizontalSpeed(13)
			inst.components.complexprojectile:SetGravity(-35)
			inst.components.complexprojectile:SetLaunchOffset(Vector3(.25, 1, 0))
			inst.components.complexprojectile:SetOnLaunch(OnPotionThrown)
			inst.components.complexprojectile:SetOnHit(OnProjectileDamage)
		end

		inst.Light:SetIntensity(.9)
		inst.Light:SetRadius(.3)
		inst.Light:SetFalloff(.6)

		inst.AnimState:SetBloomEffectHandle("shaders/anim.ksh")

		if lightcolor ~= nil then
			inst.Light:SetColour(lightcolor.x, lightcolor.y, lightcolor.z)
			inst.Light:Enable(true)
		end
	end

		inst:AddComponent("inspectable")

		inst:AddComponent("stackable")
		inst.components.stackable.maxsize = TUNING.STACK_SIZE_LARGEITEM

		inst:AddComponent("inventoryitem")
		inst.components.inventoryitem.imagename = (prefabname.."icon")
		inst.components.inventoryitem.atlasname = ("images/inventoryimages/"..prefabname.."icon.xml")

		MakeHauntableLaunch(inst)

        return inst
    end

    return Prefab(prefabname, fn, assets)
end

return MakeDonPotion("donpotionempty", "potion_empty", "none", nil, nil),
	   MakeDonPotion("donpotionstrange", "potion_strange", "strange", "eat", Vector3(53/255, 53/255, 53/255)),
	   MakeDonPotion("donpotionlife", "potion_life", "life", "eat", Vector3(255/255, 91/255, 91/255)),
	   MakeDonPotion("donpotionfood", "potion_food", "food", "eat", Vector3(234/255, 180/255, 35/255)),
	   MakeDonPotion("donpotionsanity", "potion_sanity", "sanity", "eat", Vector3(35/255, 234/255, 192/255)),
	   MakeDonPotion("donpotionlight", "potion_light", "light", "eat", Vector3(238/255, 255/255, 112/255)),
	   MakeDonPotion("donpotionmaxlife", "potion_maxlife", "maxlife", "eat", Vector3(233/255, 51/255, 255/255)),
	   MakeDonPotion("donpotionpoisonous", "potion_poisonous", "poisonous", "projectile", Vector3(236/255, 0/255, 129/255)),
	   MakeDonPotion("donpotionsleep", "potion_sleep", "sleep", "projectile", Vector3(77/255, 206/255, 36/255))
