local assets =
{
    Asset("ANIM", "anim/liwuhe_eyebone.zip"),
    Asset("ANIM", "anim/liwuhe_eyebone_build.zip"),
    Asset("ANIM", "anim/liwuhe_eyebone_snow_build.zip"),
    Asset("ANIM", "anim/liwuhe_eyebone_shadow_build.zip"),
     
    Asset("ATLAS", "images/inventoryimages/liwuhe_eyebone.xml"),
    Asset("ATLAS", "images/inventoryimages/liwuhe_eyebone_closed.xml"),
    Asset("ATLAS", "images/inventoryimages/liwuhe_eyebone_snow.xml"),
    Asset("ATLAS", "images/inventoryimages/liwuhe_eyebone_closed_snow.xml"),
    Asset("ATLAS", "images/inventoryimages/liwuhe_eyebone_shadow.xml"),
    Asset("ATLAS", "images/inventoryimages/liwuhe_eyebone_closed_shadow.xml"),
}
  
local SPAWN_DIST = 30
  
local function OpenEye(inst)
    inst.isOpenEye = true
    inst.components.inventoryitem.atlasname = "images/inventoryimages/"..inst.openEye..".xml"
    inst.components.inventoryitem:ChangeImageName(inst.openEye)
end
  
local function CloseEye(inst)
    inst.isOpenEye = nil
    inst.components.inventoryitem.atlasname = "images/inventoryimages/"..inst.closedEye..".xml"
    inst.components.inventoryitem:ChangeImageName(inst.closedEye)
end
  
local function RefreshEye(inst)
    if inst.isOpenEye then
        OpenEye(inst)
    else
        CloseEye(inst)
    end
end
  
local function MorphShadowEyebone(inst)
    inst.AnimState:SetBuild("liwuhe_eyebone_shadow_build")
  
    inst.openEye = "liwuhe_eyebone_shadow"
    inst.closedEye = "liwuhe_eyebone_closed_shadow"
    RefreshEye(inst)
  
    inst.EyeboneState = "SHADOW"
end
  
local function MorphSnowEyebone(inst)
    inst.AnimState:SetBuild("liwuhe_eyebone_snow_build")
  
    inst.openEye = "liwuhe_eyebone_snow"
    inst.closedEye = "liwuhe_eyebone_closed_snow"
    RefreshEye(inst)
  
    inst.EyeboneState = "SNOW"
end
  
--[[
local function MorphNormalEyebone(inst)
    inst.AnimState:SetBuild("liwuhe_eyebone_build")
  
    inst.openEye = "liwuhe_eyebone"
    inst.closedEye = "liwuhe_eyebone_closed"  
    RefreshEye(inst)
  
    inst.EyeboneState = "NORMAL"
end
]]
  
local function GetSpawnPoint(pt)
    local theta = math.random() * 2 * PI
    local radius = SPAWN_DIST
    local offset = FindWalkableOffset(pt, theta, radius, 12, true)
    return offset ~= nil and (pt + offset) or nil
end
  
local function Spawnliwuhe(inst)
    if not inst.owner then
        print("Error: Eyebone has no linked player!")
        return
    end
    --print("liwuhe_eyebone - Spawnliwuhe")
  
    local pt = inst:GetPosition()
    --print("    near", pt)
          
    local spawn_pt = GetSpawnPoint(pt)
    if spawn_pt ~= nil then
        --print("    at", spawn_pt)
        local liwuhe = SpawnPrefab("personal_liwuhe")
        if liwuhe ~= nil then
            liwuhe.Physics:Teleport(spawn_pt:Get())
            liwuhe:FacePoint(pt:Get())
            if inst.owner then
                inst.owner.liwuhe = liwuhe
            end
            return liwuhe
        end
  
    --else
        -- this is not fatal, they can try again in a new location by picking up the bone again
        --print("liwuhe_eyebone - Spawnliwuhe: Couldn't find a suitable spawn point for liwuhe")
    end
end
  
local StartRespawn
  
local function StopRespawn(inst)
    --print("liwuhe_eyebone - StopRespawn")
    if inst.respawntask ~= nil then
        inst.respawntask:Cancel()
        inst.respawntask = nil
        inst.respawntime = nil
    end
end
  
local function Rebindliwuhe(inst, liwuhe)
    liwuhe = liwuhe or (inst.owner and inst.owner.liwuhe)
    if liwuhe ~= nil then
        if inst.owner then
            liwuhe.components.named:SetName(inst.owner.name.."'s liwuhe")
        end
        inst.AnimState:PlayAnimation("idle_loop", true)
        OpenEye(inst)
        inst:ListenForEvent("death", function()
            if inst.owner then
                inst.owner.liwuhe = nil
            end
            StartRespawn(inst, TUNING.CHESTER_RESPAWN_TIME)
        end, liwuhe)
  
        if liwuhe.components.follower.leader ~= inst then
            liwuhe.components.follower:SetLeader(inst)
        end
        return true
    end
end
  
local function Respawnliwuhe(inst)
    --print("liwuhe_eyebone - Respawnliwuhe")
    StopRespawn(inst)
    Rebindliwuhe(inst, (inst.owner and inst.owner.liwuhe) or Spawnliwuhe(inst))
end
  
StartRespawn = function(inst, time)
    StopRespawn(inst)
  
    time = time or 0
    inst.respawntask = inst:DoTaskInTime(time, Respawnliwuhe)
    inst.respawntime = GetTime() + time
    inst.AnimState:PlayAnimation("dead", true)
    CloseEye(inst)
end
  
local function Fixliwuhe(inst)
    inst.fixtask = nil
    --take an existing liwuhe if there is one
    if not Rebindliwuhe(inst) then
        inst.AnimState:PlayAnimation("dead", true)
        CloseEye(inst)
          
        if inst.components.inventoryitem.owner ~= nil then
            local time_remaining = 0
            local time = GetTime()
            if inst.respawntime and inst.respawntime > time then
                time_remaining = inst.respawntime - time        
            end
            StartRespawn(inst, time_remaining)
        end
    end
end
  
local function OnPutInInventory(inst)
    if inst.fixtask == nil then
        inst.fixtask = inst:DoTaskInTime(1, Fixliwuhe)
    end
end
  
  
local function OnSave(inst, data)
    --print("liwuhe_eyebone - OnSave")
    --data.EyeboneState = inst.EyeboneState
    if inst.respawntime ~= nil then
        local time = GetTime()
        if inst.respawntime > time then
            data.respawntimeremaining = inst.respawntime - time
        end
    end
end
  
local function OnLoad(inst, data)
    if data == nil then
        return
    end
  
    if data.EyeboneState == "SHADOW" then
        MorphShadowEyebone(inst)
    elseif data.EyeboneState == "SNOW" then
        MorphSnowEyebone(inst)
    end
  
    if data.respawntimeremaining ~= nil then
        inst.respawntime = data.respawntimeremaining + GetTime()
    end
end
  
  
local function GetStatus(inst)
    --print("smallbird - GetStatus")
    if inst.respawntask ~= nil then
        return "WAITING"
    end
end
  
local function fn()
    local inst = CreateEntity()
  
    inst.entity:AddTransform()
    inst.entity:AddAnimState()
    inst.entity:AddNetwork()
  
    --so I can find the thing while testing
    --inst.entity:AddMiniMapEntity()
    --inst.MiniMapEntity:SetIcon("treasure.png")
  
    MakeInventoryPhysics(inst)
  
    inst:AddTag("personal_liwuhe_eyebone")
    inst:AddTag("irreplaceable")
    inst:AddTag("nonpotatable")
      
    inst:AddTag("_named")
  
    inst.AnimState:SetBank("eyebone")
    inst.AnimState:SetBuild("liwuhe_eyebone_build")
    inst.AnimState:PlayAnimation("idle_loop", true)
  
    inst.entity:SetPristine()
  
    if not TheWorld.ismastersim then
        return inst
    end
      
    -- liwuhe will not be saved normally. He is saved with the player.
    inst.persists = false
  
    inst:AddComponent("inventoryitem")
    inst.components.inventoryitem.atlasname = "images/inventoryimages/liwuhe_eyebone.xml"
    inst.components.inventoryitem:ChangeImageName("liwuhe_eyebone")
    inst.components.inventoryitem:SetOnPutInInventoryFn(OnPutInInventory)
  
    inst.EyeboneState = "NORMAL"
    inst.openEye = "liwuhe_eyebone"
    inst.closedEye = "liwuhe_eyebone_closed"
  
    inst.isOpenEye = nil
    OpenEye(inst)
  
    inst:AddComponent("inspectable")
    inst.components.inspectable.getstatus = GetStatus
    inst.components.inspectable:RecordViews()
    inst.components.inspectable.nameoverride = "liwuhe_eyebone"
  
    inst:AddComponent("leader")
      
      
    inst:AddComponent("named")
  
    MakeHauntableLaunch(inst)
  
    --inst.MorphNormalEyebone = MorphNormalEyebone
    inst.MorphSnowEyebone = MorphSnowEyebone
    inst.MorphShadowEyebone = MorphShadowEyebone
  
    inst.OnLoad = OnLoad
    inst.OnSave = OnSave
  
    inst.fixtask = inst:DoTaskInTime(1, Fixliwuhe)
    inst.Rebindliwuhe = Rebindliwuhe
  
    return inst
end
  
return Prefab("common/inventory/personal_liwuhe_eyebone", fn, assets)