const e=require("b4a"),{ReactionSchema:t}=require("@holepunchto/keet-core-schemas"),{AddReactionOperation:i,RemoveReactionOperation:s}=t.Operations,a=e.alloc(1);module.exports=class{static Operations=new Set([i.TYPE,s.TYPE]);constructor(e){this.view=e,this.chat=null,this.members=null,this.reactions=null,this.reactionDigests=null,this.reactionsByMember=null}initialize(){this.chat=this.view.chat,this.members=this.view.members,this.reactions=this.view.collections.reactions,this.reactionDigests=this.view.indexes.reactionDigests,this.reactionsByMember=this.view.indexes.reactionsByMember}async _applyAddReactionOperation(e,{id:t}){const{to:i,text:s}=e.value,[n,o,c]=await Promise.all([this.members.getMemberForDeviceKey(t.key),this.chat.getEventId(i),this.members.isDeviceMuted(t.key)]);!c&&n&&o&&await this.reactions.update([...o,n.key,s],a,{upsert:!0})}async _applyRemoveReactionOperation(e,{id:t}){const{to:i,text:s}=e.value,[a,n,o]=await Promise.all([this.members.getMemberForDeviceKey(t.key),this.chat.getEventId(i),this.members.isDeviceMuted(t.key)]);o||a&&n&&a&&n&&await this.reactions.get([...n,a.key,s])&&await this.reactions.delete([...n,a.key,s])}async _indexReactionDigests(t,i,s){const[a,n,o,c]=s,r=[a,n,o],h=[a,n],l=await this.reactionsByMember.get(r),m=l?.value,u=await this.reactionDigests.get(h),d=u?u.value:{total:0,reactions:[]};t&&i||(t&&(function(t,i,s){const a=t.reactions.findIndex(e=>e.text===s);if(-1===a)return;const n=t.reactions[a];if(n.count-=1,n.count>0){const t=n.latest.findIndex(t=>{return s=t,a=i,e.equals(s,a);var s,a});-1!==t&&n.latest.splice(t,1)}else t.reactions.splice(a,1);t.reactions.sort()}(d,o,c),m&&m.length<=1&&(d.total-=1)),i&&(function(e,t,i){const s=e.reactions.findIndex(e=>e.text===i);if(-1!==s){const i=e.reactions[s];i.count+=1,i.latest.unshift(t),i.latest.length>3&&i.latest.pop()}else e.reactions.push({text:i,count:1,latest:[t]});e.reactions.length>32&&e.reactions.pop(),e.reactions.sort()}(d,o,c),m||(d.total+=1)),d.total>0?await this.reactionDigests.insert(h,d):await this.reactionDigests.delete(h))}async _indexReactionsByMember(e,t,i){const[s,a,n,o]=i,c=[s,a,n],r=await this.reactionsByMember.get(c),h=r?.value;if(e&&h){const e=h.indexOf(o);-1!==e&&(h.splice(e,1),h.length>0?await this.reactionsByMember.insert(c,h):await this.reactionsByMember.delete(c))}t&&(h?-1===h.indexOf(o)&&(h.push(o),h.sort(),await this.reactionsByMember.insert(c,h)):await this.reactionsByMember.insert(c,[o]))}autobaseApply(e,t){switch(e.type){case i.TYPE:return this._applyAddReactionOperation(e,t);case s.TYPE:return this._applyRemoveReactionOperation(e,t)}}async autobaseIndex({prev:e,next:t,id:i}){await this._indexReactionDigests(e,t,i),await this._indexReactionsByMember(e,t,i)}};