export default class Activity{constructor(e){this.#e=e,this.#t=setInterval((()=>this.heartbeat(this)),15e3),this.#i()}#e;#t;users={};worldTime;#s;queries=new Map;#i(){this.#s=Date.now(),db.Setting.getValue("core.time").then((e=>{if(this.worldTime=Number.isNumeric(e)?Number(e):0,void 0===e)return db.Setting.set("core.time",0)}))}get serverTime(){return Date.now()-this.#s}heartbeat(){if(game.world===this.#e){if(game.users)for(let e of game.users)e.id in this.users&&0===e.sockets.length&&this.deactivateUser(e)}else clearInterval(this.#t)}activateUser(e){const{express:t,game:i,db:s}=global;return"string"==typeof e&&(e=i.users.find((t=>t.id===e))),e instanceof s.User&&(!(e.id in this.users)&&(this.users[e.id]={},t.io.emit("userActivity",e.id,{active:!0}),!0))}deactivateUser(e){const{express:t,db:i}=global;if(!(e instanceof i.User))throw new Error("You must provide a User document instance to the deactivateUser method");return!e.sockets.length&&(e.id in this.users&&(delete this.users[e.id],t.io.emit("userActivity",e.id,{active:!1})),!0)}static socketListeners(e){this._onActivate(e,!0),e.on("disconnect",(()=>this._onActivate(e,!1))),e.on("userActivity",((t,i)=>Activity.#r(e,t,i))),e.on("getUserActivity",(()=>Activity.#a(e))),e.on("userQuery",((t,i,s,r,a,o)=>{Activity.#o(e,t,i,s,r,a,o)})),e.on("pause",((...t)=>this.pause(e,...t))),e.on("time",Activity.#c.bind(Activity)),e.on("reload",(()=>{e.user.can("SETTINGS_MODIFY")&&e.broadcast.emit("reload")}))}static _onActivate(e,t){const{game:i}=global;i.ready&&i.activity&&e.user&&(t?i.activity.activateUser(e.user):i.activity.deactivateUser(e.user))}static async#c(e){const{game:t}=global;return t.ready&&t.activity?e({serverTime:t.activity.serverTime,worldTime:t.activity.worldTime}):e({})}static pause(e,t,i){game.ready&&e.user.isGM&&(global.logger.info(`Toggling game pause status to ${t}`),game.paused=t,i.userId=e.user.id,e.broadcast.emit("pause",t,i))}static#r(e,t,i={}){if(!game.ready||!game.activity)return;const s=game.activity.users;t in s||(s[t]={});const r=s[t];for(const e of["sceneId","cursor","ruler","targets","av"])e in i&&(r[e]=i[e]);e.broadcast.emit("userActivity",t,i)}static async#o(e,t,i,s,r,a,o){const c=e.user;if(!c.hasPermission("QUERY_USER"))return void o({status:"rejected",reason:`User [${c.id}] does not have permission to query users`});const n=game.users.find((e=>e.id===t));if(!n)return void o({status:"rejected",reason:`User [${t}] does not exist or is not active`});let{timeout:d}=a;"number"!=typeof d&&(d=void 0),a={timeout:d},game.activity.queries.set(i,{id:i,name:s,data:r,options:a,sender:c,recipient:n});const u=()=>{o&&(o({status:"rejected",reason:`User [${t}] has disconnected`}),o=void 0,game.activity.queries.delete(i))};e.once("disconnect",u);const m=t=>{o&&(o(t),o=void 0,e.off("disconnect",u),game.activity.queries.delete(i))};void 0!==d?n.sockets.forEach((e=>{e.timeout(d).emit("userQuery",c.id,i,s,r,a,((e,t)=>{m(e?{status:"rejected",reason:e.message}:t)}))})):n.sockets.forEach((e=>e.emit("userQuery",c.id,i,s,r,a,m)))}static#a(e){if(game.ready&&game.activity)for(const[t,i]of Object.entries(game.activity.users))e.emit("userActivity",t,i)}}