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

]]

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

local pests_mobs = {
{originalmob = "rabbit", replacemob = "spider", deleteaftsp = true, sanitydropplayer = 6},

{originalmob = "spider", replacemob = "spider_warrior", deleteaftsp = true, sanitydropplayer = 12},

{originalmob = "crow", replacemob = "bat", deleteaftsp = true, sanitydropplayer = 11},
{originalmob = "robin", replacemob = "bat", deleteaftsp = true, sanitydropplayer = 11},
{originalmob = "robin_winter", replacemob = "bat", deleteaftsp = true, sanitydropplayer = 11},
{originalmob = "canary", replacemob = "bat", deleteaftsp = true, sanitydropplayer = 11},

{originalmob = "mole", replacemob = "frog", deleteaftsp = true, sanitydropplayer = 5},

{originalmob = "bee", replacemob = "mosquito", deleteaftsp = true, sanitydropplayer = 8},
{originalmob = "killerbee", replacemob = "mosquito", deleteaftsp = true, sanitydropplayer = 8}
}

local normal_mobs = {
{originalmob = "spider", replacemob = "rabbit", deleteaftsp = true, sanitydropplayer = 6},
{originalmob = "spider_warrior", replacemob = "spider", deleteaftsp = true, sanitydropplayer = 12},
{originalmob = "bat", replacemob = "robin", deleteaftsp = true, sanitydropplayer = 11},
{originalmob = "frog", replacemob = "mole", deleteaftsp = true, sanitydropplayer = 5},
{originalmob = "mosquito", replacemob = "bee", deleteaftsp = true, sanitydropplayer = 8}
}

local function weapon_don_night_trail_fx(inst)
    local owner = inst.components.inventoryitem:GetGrandOwner() or inst
    if not owner.entity:IsVisible() then
        return
    end

    local x, y, z = owner.Transform:GetWorldPosition()
    if owner.sg ~= nil and owner.sg:HasStateTag("moving") then
        local theta = -owner.Transform:GetRotation() * DEGREES
        local speed = owner.components.locomotor:GetRunSpeed() * .1
        x = x + speed * math.cos(theta)
        z = z + speed * math.sin(theta)
    end
    local mounted = owner.components.rider ~= nil and owner.components.rider:IsRiding()
    local map = TheWorld.Map
    local offset = FindValidPositionByFan(
        math.random() * 2 * PI,
        (mounted and 1 or .5) + math.random() * .5,
        4,
        function(offset)
            local pt = Vector3(x + offset.x, 0, z + offset.z)
            return map:IsPassableAtPoint(pt:Get())
                and not map:IsPointNearHole(pt)
                and #TheSim:FindEntities(pt.x, 0, pt.z, .7, { "shadowtrail" }) <= 0
        end
    )

    if offset ~= nil then
        local fxwalk = SpawnPrefab(inst.fxgroundname)
        fxwalk.Transform:SetPosition(x + offset.x, 0, z + offset.z)
    end
end

local function onequip(inst, owner)
    owner.AnimState:OverrideSymbol("swap_object", "swap_weapons_don", inst.wpanimswap)
    owner.AnimState:Show("ARM_carry")
    owner.AnimState:Hide("ARM_normal")
	
	if inst._trailtask == nil and inst.usefxwpground == true and inst.fxgroundname ~= nil then
        inst._trailtask = inst:DoPeriodicTask(6 * FRAMES, weapon_don_night_trail_fx, 2 * FRAMES)
    end
end

local function onunequip(inst, owner)
    owner.AnimState:Hide("ARM_carry")
    owner.AnimState:Show("ARM_normal")
	
	if inst._trailtask ~= nil then
        inst._trailtask:Cancel()
        inst._trailtask = nil
    end

end


local function onattack_melee(inst)
    
end


local function onattack_spell(inst, attacker, target, skipsanity)
    if not skipsanity and attacker ~= nil and attacker.components.sanity ~= nil then
        attacker.components.sanity:DoDelta(-TUNING.SANITY_SUPERTINY)
    end

	attacker.SoundEmitter:PlaySound("dontstarve/common/gem_shatter")

    if not target:IsValid() then
        --target killed or removed in combat damage phase
        return
    end
		
    if target.components.sleeper ~= nil and target.components.sleeper:IsAsleep() then
        target.components.sleeper:WakeUp()
    end

    if target.components.combat ~= nil then
        target.components.combat:SuggestTarget(attacker)
    end

	if target ~= nil then
		
		if inst.powername == "pestsmob" then
			attacker.SoundEmitter:PlaySound("dontstarve/common/staff_dissassemble")
			
			for k,v in ipairs(pests_mobs) do
				if target.prefab == v.originalmob then				
					--spawn new mob:
					local newmobsp = SpawnPrefab(v.replacemob)
					newmobsp.Transform:SetPosition(target.Transform:GetWorldPosition())					
					newmobsp:PushEvent("attacked", { attacker = attacker, damage = 0, weapon = inst }) --damage
					
					--print("---drop sanity: "..v.sanitydropplayer)

					--remove old mob
					if v.deleteaftsp == true then
						target:Remove()
					end
					
					if attacker.components.sanity ~= nil then
						attacker.components.sanity:DoDelta(-v.sanitydropplayer)
					end
					
					--fx:
					SpawnPrefab("donfx_shadow_despawn_purple").Transform:SetPosition(target.Transform:GetWorldPosition())
					SpawnPrefab("donfx_red_smoke").Transform:SetPosition(target.Transform:GetWorldPosition())
				end
			end
					
		end
		
		
		if inst.powername == "animalsmob" then
			attacker.SoundEmitter:PlaySound("dontstarve/common/staff_dissassemble")
			
			for k,v in ipairs(normal_mobs) do
				if target.prefab == v.originalmob then				

					local newmobsp = SpawnPrefab(v.replacemob)
					newmobsp.Transform:SetPosition(target.Transform:GetWorldPosition())					

					if v.deleteaftsp == true then
						target:Remove()
					end
					
					if attacker.components.sanity ~= nil then
						attacker.components.sanity:DoDelta(-v.sanitydropplayer)
					end

					SpawnPrefab("donfx_shadow_despawn_pink").Transform:SetPosition(target.Transform:GetWorldPosition())
					SpawnPrefab("donfx_cyan_smoke").Transform:SetPosition(target.Transform:GetWorldPosition())
				end
			end
			
		end
		
		
		if inst.powername == "teleporteyetomob" then
			SpawnPrefab("donfx_shadow_despawn_yellow").Transform:SetPosition(attacker.Transform:GetWorldPosition())
			
			inst:DoTaskInTime(0.5, function() 
				attacker.SoundEmitter:PlaySound("dontstarve/common/staffteleport")
				
				if attacker.Physics ~= nil then
					attacker.Physics:Teleport(target.Transform:GetWorldPosition())
				else
					attacker.Transform:SetPosition(target.Transform:GetWorldPosition())
				end
				
				if attacker.components.sanity ~= nil then
					attacker.components.sanity:DoDelta(-5)
				end
				
				---
				if target.components.burnable ~= nil then
					if target.components.burnable:IsBurning() then
					target.components.burnable:Extinguish()
					elseif target.components.burnable:IsSmoldering() then
					target.components.burnable:SmotherSmolder()
					end
				end

				if target.components.freezable ~= nil then					
					target.components.freezable:Freeze()	
					target.components.freezable:SpawnShatterFX()
				end
				---
				
				SpawnPrefab("donfx_yellow_smoke").Transform:SetPosition(target.Transform:GetWorldPosition())
			end)
			
		end
		
		
	end
	
end

local function MakeDonWeapon(prefabname, animground, animswap, wptype, powername, usefxwpground, fxgroundname, fxprojectile)
local function fn()
    local inst = CreateEntity()

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

    MakeInventoryPhysics(inst)
	
	inst.wpanimswap = animswap
	inst.usefxwpground = usefxwpground
	inst.fxgroundname = fxgroundname
	inst.powername = powername
	
	inst.Light:SetIntensity(.3)
	inst.Light:SetRadius(.2)
	inst.Light:SetFalloff(.6)
	inst.Light:SetColour(130/255, 44/255, 198/255)
	inst.Light:Enable(true)
	inst.AnimState:SetBloomEffectHandle("shaders/anim.ksh")

    inst.AnimState:SetBank("ground_weapons_don")
    inst.AnimState:SetBuild("ground_weapons_don")
    inst.AnimState:PlayAnimation(animground)

    inst:AddTag("sharp")
    inst:AddTag("pointy")
	inst:AddTag("shadow") --don

    inst.entity:SetPristine()

    if not TheWorld.ismastersim then
        return inst
    end

    inst:AddComponent("weapon")
    
	if wptype == "melee" then
		inst.components.weapon:SetDamage(TUNING.SPEAR_DAMAGE+(TUNING.SPEAR_DAMAGE/2.5))
		inst.components.weapon:SetOnAttack(onattack_melee)
	end
	
	if wptype == "spell" then
		inst.components.weapon:SetDamage(0)
		inst.components.weapon:SetRange(8, 10)
		inst.components.weapon:SetOnAttack(onattack_spell)
		inst.components.weapon:SetProjectile(fxprojectile)
	end

    -------

    inst:AddComponent("finiteuses")
    inst.components.finiteuses:SetMaxUses(TUNING.YELLOWSTAFF_USES-3)
    inst.components.finiteuses:SetUses(TUNING.YELLOWSTAFF_USES-3)
    inst.components.finiteuses:SetOnFinished(inst.Remove)

    inst:AddComponent("inspectable")

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

    inst:AddComponent("equippable")
    inst.components.equippable:SetOnEquip(onequip)
    inst.components.equippable:SetOnUnequip(onunequip)
	inst.components.equippable.dapperness = TUNING.CRAZINESS_MED --don

    MakeHauntableLaunch(inst)

        return inst
    end

    return Prefab(prefabname, fn, assets)
end

return MakeDonWeapon("donrpgweapon_eyeteleport", "don_weapon_eye", "swap_don_weapon_eye", "spell", "teleporteyetomob", true, "weapondon_shadow_fx_yellow", "fire_projectile"),
	   MakeDonWeapon("donrpgweapon_pests", "don_weapon_pests", "swap_don_weapon_pests", "spell", "pestsmob", true, "weapondon_shadow_fx_purple", "ice_projectile"),
	   MakeDonWeapon("donrpgweapon_animals", "don_weapon_animals", "swap_don_weapon_animals", "spell", "animalsmob", true, "weapondon_shadow_fx_multicolor", "ice_projectile")
