
local assets =
{
    Asset("ANIM", "anim/tf2madmilk.zip"),
    Asset("ANIM", "anim/swap_tf2madmilk.zip"),

    Asset("ATLAS", "images/inventoryimages/tf2madmilk.xml"),
    Asset("IMAGE", "images/inventoryimages/tf2madmilk.tex"),
}

local prefabs =
{
    "waterballoon_splash",
    "reticule",
}

local function OnHitMilk(inst, attacker, target)
    SpawnPrefab("waterballoon_splash").Transform:SetPosition(inst.Transform:GetWorldPosition())
	inst.SoundEmitter:PlaySound("dontstarve/common/gem_shatter")
	inst.components.wateryprotection:SpreadProtection(inst)
    FindEntity(inst, 5, function(other)
	if TheNet:GetPVPEnabled() then

	    if other and other:HasTag("player") and other ~= attacker then
                if other.components.inventoryitem ~= nil then
                    other.components.inventoryitem:AddMoisture(20)
                end
	    end
	    if other and other == attacker or other:HasTag("structure") or other:HasTag("madmilked") then
	        return
	    end
	end
	if not TheNet:GetPVPEnabled() then

	    if other and other == attacker or other:HasTag("structure") or other:HasTag("player") or other:HasTag("madmilked") then
	        return
	    end
	end
	if other and other.components.combat then
	    other:AddTag("madmilked")

	    if other and other.AnimState then
		other.AnimState:SetAddColour(.5,.5,.5,0)
	    end

	    other.refunddamage = function(other, data)
		if data.attacker and data.attacker.components.health and data.attacker.components.health:GetPercent() < 1 and data.damage > 0 then
		    data.attacker.components.health:DoDelta(data.damage / 2,false,data.weapon)
		end
    	    end
	    other:ListenForEvent("attacked", other.refunddamage, other)
	    other.milktask = other:DoTaskInTime(TUNING.MADMILKED_DURATION, function()
		other:RemoveTag("madmilked")
	    	other.AnimState:SetAddColour(0,0,0,0)
		other:RemoveEventCallback("attacked", other.refunddamage, other)
	    end)
	end
    end)

    inst:Remove()
end

local function common_fn(bank, build, anim, tag, isinventoryitem)
    local inst = CreateEntity()

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

    if isinventoryitem then
        MakeInventoryPhysics(inst)
    else
        inst.entity:AddPhysics()
        inst.Physics:SetMass(1)
        inst.Physics:SetFriction(0)
        inst.Physics:SetDamping(0)
        inst.Physics:SetCollisionGroup(COLLISION.CHARACTERS)
        inst.Physics:ClearCollisionMask()
        inst.Physics:CollidesWith(COLLISION.WORLD)
        inst.Physics:SetCapsule(0.2, 0.2)
        inst.Physics:SetDontRemoveOnSleep(true)
    end

    if tag ~= nil then
        inst:AddTag(tag)
    end

    --projectile (from complexprojectile component) added to pristine state for optimization
    inst:AddTag("projectile")
	
	inst:AddComponent("wateryprotection")

    inst.AnimState:SetBank(bank)
    inst.AnimState:SetBuild(build)
    inst.AnimState:PlayAnimation(anim, true)
	inst.AnimState:SetDeltaTimeMultiplier(.75)

    inst.entity:SetPristine()

    if not TheWorld.ismastersim then
        return inst
    end

    inst:AddComponent("locomotor")


    inst:AddComponent("complexprojectile")

    return inst
end

local function onequip(inst, owner) 
    owner.AnimState:OverrideSymbol("swap_object", "swap_tf2madmilk", "tf2madmilk")
    owner.AnimState:Show("ARM_carry") 
    owner.AnimState:Hide("ARM_normal") 
end

local function onunequip(inst, owner) 
    owner.AnimState:Hide("ARM_carry") 
    owner.AnimState:Show("ARM_normal") 
end

local function onthrown(inst)
    inst:AddTag("NOCLICK")
    inst.persists = false

    inst.AnimState:PlayAnimation("spin_loop", true)

    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)
	
--[[	local owner = inst.components.inventoryitem ~= nil and inst.components.inventoryitem.owner or nil
    if owner and owner:HasTag("tf2scout") then
    owner.components.talker:Say(GetString(owner, "ANNOUNCE_THROW"))
	end --]]
end

local function ReticuleTargetFn()
    local player = ThePlayer
    local ground = TheWorld.Map
    local pos = Vector3()
    --Attack range is 8, leave room for error
    --Min range was chosen to not hit yourself (2 is the hit range)
    for r = 6.5, 3.5, -.25 do
        pos.x, pos.y, pos.z = player.entity:LocalToWorldSpace(r, 0, 0)
        if ground:IsPassableAtPoint(pos:Get()) and not ground:IsPointNearHole(pos) then
            return pos
        end
    end
    return pos
end

local function madmilk_fn()
    local inst = common_fn("tf2madmilk", "tf2madmilk", "idle", nil, true)

    inst:AddComponent("reticule")
    inst.components.reticule.targetfn = ReticuleTargetFn
    inst.components.reticule.ease = true

    inst:AddTag("nopunch")

    if not TheWorld.ismastersim then
        return inst
    end

    inst.components.complexprojectile:SetHorizontalSpeed(15)
    inst.components.complexprojectile:SetGravity(-35)
    inst.components.complexprojectile:SetLaunchOffset(Vector3(.25, 1, 0))
    inst.components.complexprojectile:SetOnLaunch(onthrown)
    inst.components.complexprojectile:SetOnHit(OnHitMilk)
	
	inst.components.wateryprotection.extinguishheatpercent = TUNING.WATERBALLOON_EXTINGUISH_HEAT_PERCENT
    inst.components.wateryprotection.temperaturereduction = TUNING.WATERBALLOON_TEMP_REDUCTION
    inst.components.wateryprotection.witherprotectiontime = TUNING.WATERBALLOON_PROTECTION_TIME
--  inst.components.wateryprotection.addwetness = TUNING.WATERBALLOON_ADD_WETNESS

    inst:AddComponent("inspectable")

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

    inst:AddComponent("stackable")

    inst:AddComponent("equippable")
    inst.components.equippable:SetOnEquip(onequip)
    inst.components.equippable:SetOnUnequip(onunequip)
    inst.components.equippable.equipstack = true

    MakeHauntableLaunch(inst)

    return inst
end

STRINGS.TF2MADMILK = "Mad Milk"
STRINGS.NAMES.TF2MADMILK = "Mad Milk"
STRINGS.RECIPE_DESC.TF2MADMILK = "Makes milk mad."

return Prefab("tf2madmilk", madmilk_fn, assets, prefabs)