const e=require("b4a"),{ChatSchema:t}=require("@holepunchto/keet-core-schemas"),{FEATURES:i,GENERIC_EVENTS:s,DISPLAY_TYPES:a,isDisplaySupported:n}=require("@holepunchto/keet-core-api"),{PRIMARY_THREAD_ID:r}=t.Messages,{AddChatMessageOperation:l,AddFileOperation:o,AddGenericEventOperation:d,RemoveChatMessageOperation:p,RemoveFileOperation:h,RemoveGenericEventOperation:y,UpdateChatMessageOperation:c}=t.Operations,u=new Set([s.CALL_STARTED,s.ROOM_AVATAR_CHANGED,s.CALL_HANGUP,s.CALL_MISSED]);function v(e){return e.filter(e=>e.type===a.MENTION)}function m(e){return!!e.replyTo}async function w(e,t){const i=await e.get(t);return i?i.value:null}module.exports=class{static Operations=new Set([l.TYPE,c.TYPE,p.TYPE,d.TYPE,y.TYPE,o.TYPE,h.TYPE]);constructor(e){this.view=e,this.members=null,this.config=null,this.chat=null,this.mentionsByMemberId=null,this.eventIdsByMemberId=null,this.eventIdsByMessageid=null,this.eventIdsByClock=null,this.drivesByPath=null}initialize(){this.members=this.view.members,this.config=this.view.config,this.chat=this.view.collections.chat,this.mentionsByMemberId=this.view.indexes.mentionsByMemberId,this.eventIdsByMessageId=this.view.indexes.eventIdsByMessageId,this.eventIdsByClock=this.view.indexes.eventIdsByClock,this.drivesByPath=this.view.indexes.drivesByPath}async _ensureMemberCanChat({id:e}){return!(await this.config.isBroadcastRoom()&&!await this.members.isModerator(e.key))}_applyAddChatMessageOperation(e,{id:t,timestamp:i}){const{replyTo:s,parent:a,display:n,...r}=e.value;return this.addMessage({id:t,timestamp:i,clock:0,chat:r,parent:a,display:n,replyTo:s})}_applyAddFileOperation(e,{id:t,timestamp:i}){const s={id:t,timestamp:i,clock:0,parent:e.value.parent,file:e.value.file,chat:e.value.description?{text:e.value.description}:null};return this.addMessage(s)}async _applyAddGenericEventOperation(e,{id:t,timestamp:a}){if(u.has(e.value.type)&&!(e.value.type===s.CALL_HANGUP&&await this.view.isUnsupportedFeature(i.CALL_HANGUP_EVENT)||e.value.type===s.CALL_MISSED&&await this.view.isUnsupportedFeature(i.CALL_MISSED_EVENT)))return this.addMessage({id:t,timestamp:a,clock:0,event:e.value})}async _applyUpdateChatMessageOperation(t,{id:s}){if(m(t.value)&&await this.view.isUnsupportedFeature(i.REPLY_TO))return;const a=t.value.id,r=await w(this.eventIdsByMessageId,[a.key,a.seq]);if(!r)return;const l=await w(this.chat,r);if(!l)return;const[o,d,p]=await Promise.all([this.members.isModerator(s.key),this.members.getMemberForDeviceKey(s.key),this.members.getMemberForDeviceKey(a.key)]);if(e.equals(d.key,p.key)||o){const e=t.value;if(e.display){const t=await this.view.internal.getCodeVersion();e.display=e.display.filter(e=>n(t,e.type))}await this.chat.update(r,{...l,replyTo:e.replyTo,display:e.display,chat:{text:e.text,edited:!0}})}}async _applyRemovalOperation(t,{id:i}){const s=t.value.id,a=await w(this.eventIdsByMessageId,[s.key,s.seq]);if(!a)return;const n=await this.chat.get(a);if(!n)return;const r=n.value,[l,o,d,p]=await Promise.all([this.members.isModerator(i.key),this.members.getMemberForDeviceKey(i.key),this.members.getMemberForDeviceKey(s.key),this.members.getInactiveMemberForDeviceKey(s.key)]),h=d||p;(e.equals(o.key,h.key)||l)&&(await this.config.deletePinnedMessageIfExists(s),await this.chat.update(a,{...r,chat:null,file:null,event:null,deleted:!0}))}_applyRemoveChatMessageOperation(e,t){return this._applyRemovalOperation(e,t)}_applyRemoveFileOperation(e,t){return this._applyRemovalOperation(e,t)}_applyRemoveGenericEventOperation(e,t){return this._applyRemovalOperation(e,t)}async _indexClocks(e,t,i){t&&!e&&(await this.eventIdsByClock.insert(t.clock,i),await this.eventIdsByMessageId.insert([t.id.key,t.id.seq],i))}async _indexMentions(e,t,i){const s=e?.display&&v(e.display),a=t?.display&&v(t.display);if(s)for(const{value:e}of s)await this.mentionsByMemberId.delete([e.memberId,...i]);if(a)for(const{value:e}of a)await this.mentionsByMemberId.insert([e.memberId,...i])}async _indexDrivesByPath(t,i){var s,a;t&&i&&(s=t.file,a=i.file,!s&&!a||s&&a&&e.equals(s.key,a.key)&&s.path===a.path&&s.version===a.version)&&t?.file&&await this.drivesByPath.delete([t.file.path,t.file.key,t.file.version]),i?.file&&await this.drivesByPath.insert([i.file.path,i.file.key,i.file.version])}async getThreadLength(e){const t=await this.chat.peek({gte:[e],lte:[e],reverse:!0});return t?t._id[1]+1:0}async messageExists(e){const t=await this.getMessageById(e);return t&&!0!==t?.value?.deleted}async getMessageById(e){const t=await this.getEventId(e);return t?await this.chat.get(t):null}async getEventId(e){const t=await this.eventIdsByMessageId.get([e.key,e.seq]);return t?t.value:null}async addMessage(e){const[t,s,a,l,o]=await Promise.all([this.view.internal.getCodeVersion(),this.view.isUnsupportedFeature(i.REPLY_TO),e.parent?w(this.eventIdsByMessageId,e.parent):null,this.eventIdsByClock.peek({reverse:!0}),this.view.members.isDeviceMuted(e.id.key)]);if(m(e)&&s||o)return;let d=r;a&&(d=a.clock+1);const p=await this.getThreadLength(d);e.clock=l?l.key+1:0,e.display&&(e.display=e.display.filter(e=>n(t,e.type))),await this.chat.update([d,p],e,{upsert:!0})}async autobaseApply(e,t){if(await this._ensureMemberCanChat(t))switch(e.type){case l.TYPE:return this._applyAddChatMessageOperation(e,t);case o.TYPE:return this._applyAddFileOperation(e,t);case d.TYPE:return this._applyAddGenericEventOperation(e,t);case p.TYPE:return this._applyRemoveChatMessageOperation(e,t);case h.TYPE:return this._applyRemoveFileOperation(e,t);case y.TYPE:return this._applyRemoveGenericEventOperation(e,t);case c.TYPE:return this._applyUpdateChatMessageOperation(e,t)}}async autobaseIndex({prev:e,next:t,id:i}){await this._indexClocks(e,t,i),await this._indexMentions(e,t,i),await this._indexDrivesByPath(e,t,i)}};