makeclass('world')
makeclass('login')
makeclass('probe')
makeclass('invoke')
makeclass('cube')
makeclass('sphere')
makeclass('pylon')
makeclass('roster')

function pretty(t, indent, seen)
    indent = indent or 0
    seen = seen or {}

    if type(t) ~= "table" then return tostring(t) end
    if seen[t] then return "<cycle>" end
    seen[t] = true

    local spacing = string.rep("  ", indent)
    local out = "{\n"

    for k, v in pairs(t) do
        out = out .. spacing .. "  [" .. tostring(k) .. "] = "
        out = out .. pretty(v, indent + 1, seen) .. ",\n"
    end

    return out .. spacing .. "}"
end

-- tangible.redirect(actor1,actor2)
-- tangible.forcedisconnect(actor)
-- tangible.keepactor(actor)               -- Do not autodelete upon disconnect
-- tangible.delete(actor)                  -- If actor is a connected player it will disconnect

-- This gets called on every login except the admin user.
function login.init(self, config)
    local player = global.get("nextplayer") 
    global.set("nextplayer", player + 1)
    printf("login.init initializing %p, player %d", self, player)
    self.player = player
    self.color={0,0,0,0,0,0,0,0,0,0,0,0}
    self.kills=0
    self.killed=0
    tangible.animinit{tan=self, anim={bp="character", mesh="manny", plane="earth", xyz={player * 100, 0, 90}}}
    tangible.start(self, login.startscanning)
end

function login.startscanning()
    printf("Scanning started.  Actor=%p Place=%p", actor, place)
    while true do
        login.onescan()
        wait(1)
    end
end

function login.onescan()
    local nearby=tangible.find{plane=tangible.animfinal(actor).plane,center=tangible.animfinal(actor).xyz,radius=1000,shape="cylinder"}
    for k,v in pairs(nearby) do 
        if classname(v)=="pylon" then actor.color[v.color]=time()+30 end
        if classname(v)=="player" then
            if actor.team==v.team then
                for ck,cv in v.color do actor.color[ck]=math.max(actor.color[ck],cv) end
            else
                local score1=0
                local score2=0
                for ck,cv in actor.color do if time()-cv<0 then score1=score1+1 end end
                for ck,cv in v.color     do if time()-cv<0 then score2=score2+1 end end
                if score1-score2>0 then

                    -- kill player 2
                end
            end
        end
    end
end

-- This gets called on the admin user.  You can call login.init in here if you want.
function world.init(self, config)
    print("world.init")
    global.set("nextplayer", 0)
    tangible.build{class=roster, anim={plane="earth", xyz={2000,0,0} } }
    tangible.build{class=cube,   anim={plane="earth", xyz={500,-100,0}, mat_color={1,0,0}}}
    tangible.build{class=sphere, anim={plane="earth", xyz={500,100,0}, mat_color={0,0,1}}}
    login.init(self, config)
end


function roster.init(self,config)
    self.character={}
end

function world.buildpylon()
    print("Building pylon")
    local radius=1000
    tangible.build{class=pylon,plane="earth",xyz={math.random(-radius,radius),math.random(-radius,radius),0}}.color=math.random(1,12)
end

function invoke.move(action, xyz, facing)
    -- todo: sanity check the parameters.
    tangible.animate{tan=actor, anim={action=action, interactive=true, xyz=xyz, facing=facing}}
end

function moveto(x, y)
    local z = tangible.animfinal(actor).xyz[3]
    tangible.animate{tan=actor, anim={action="moveto", xyz={x, y, z}, facing=math.auto}}
end

function login.lookmenu(add)
    add("Redirect", function() tangible.redirect(actor, place) end)
end

-- Four cases: Unnamed to new, Unnamed to existing, Named to new, Named to Existing
function playas(who)
    printf("Playas %lP",place)
    if not actor.name and not place.character[who] then -- Unnamed to new
        printf("Case 1: Naming this character "..who)
        actor.name=who
        tangible.keepactor(actor)
        place.character[who]=actor
    elseif actor.name and not place.character[who] then -- Named to new (Hard one)
        printf("Case 2: Creating new character "..who)
        printf("Case 2.0")
        local nc=tangible.build{class=login, anim={plane="earth", xyz={0,0,0} } }
        printf("Case 2.1")
        nc.name=who
        printf("Case 2.2")
        tangible.keepactor(nc)
        printf("Case 2.3")
        place.character[who]=nc
        printf("Case 2.4: ...Place is now "..place)
        tangible.redirect(actor,nc)
    elseif not actor.name and place.character[who] then
        printf("Case 3: Logging in from unnamed to existing character "..who)
        tangible.redirect(actor,place.character[who])
    elseif actor.name and place.character[who] then
        printf("Case 4: Logging in from "..actor.name.." to existing character "..who)
        tangible.redirect(actor,place.character[who])
    end
end

function roster.lookmenu(add)
    for _,name in ipairs { "Albert", "Betty", "Cornelius" } do
        add("Play as "..name..(place.character[name] and "" or "*"), function() playas(name) end)
    end
end

function cube.lookmenu(add)
    add("Cube A", function () print("Doing Cube A") end)
    add("Cube B", function () print("Doing Cube B") end)
    add("Cube C", function () print("Doing Cube C") end)
    add("Cube Hi", function () print("Doing Cube Hi") end)
    add("Cube Bye", function () print("Doing Cube Bye") end)
    add("Cube Yo", function () print("Doing Cube Yo") end)
    add("Cube Z", function () print("Doing Cube Z") end)
end


function sphere.lookhotkeys(add)
    add("FaceL", "Sphere Hi", function () print("Doing Sphere Hi") end)
    add("FaceM", "Sphere Bye", function () print("Doing Sphere Bye") end)
    add("FaceR", "Sphere Yo", function () print("Doing Sphere Yo") end)
end

function sphere.tick(foo)
    print("Tick")
end


function probe.getlookat()
    local class = tangible.getclass(place)

    -- if the tangible is not of any class, return empty string.
    if class == nil then
        return ""
    end

    -- if the class has a function 'lookhotkeys', then the correct
    -- look-at widget is 'hotkeys'.
    if class.lookhotkeys ~= nil then
        return "hotkeys"
    end

    -- if the class has a function 'lookmenu', then the correct
    -- look-at widget is 'menu'.
    if class.lookmenu ~= nil then
        return "menu"
    end

    -- otherwise, if the class has a function 'getlookat', use that.
    if class.getlookat ~= nil then
        return class.getlookat()
    end

    -- by default, return the empty string.
    return ""
end

function jp3()
    tangible.animate{tan=actor, anim={action="play", seq="jump"}}
    tangible.animate{tan=actor, anim={action="play", seq="jump"}}
    tangible.animate{tan=actor, anim={action="play", seq="jump"}}
end
    
