import { MatrixClient, MatrixEvent, RoomMember, RoomMemberEvent } from 'matrix-js-sdk';
import { useEffect, useState } from 'react';

export const useRoomMembers = (mx: MatrixClient, roomId: string): RoomMember[] => {
  const [members, setMembers] = useState<RoomMember[]>([]);

  useEffect(() => {
    const room = mx.getRoom(roomId);
    let loadingMembers = true;
    let disposed = false;

    const updateMemberList = (event?: MatrixEvent) => {
      if (!room || disposed || (event && event.getRoomId() !== roomId)) return;
      if (loadingMembers) return;
      setMembers(room.getMembers());
    };

    if (room) {
      setMembers(room.getMembers());
      room.loadMembersIfNeeded().then(() => {
        loadingMembers = false;
        if (disposed) return;
        updateMemberList();
      });
    }

    mx.on(RoomMemberEvent.Membership, updateMemberList);
    mx.on(RoomMemberEvent.PowerLevel, updateMemberList);
    // Display-name changes ride `RoomMemberEvent.Name` (per
    // matrix-js-sdk `RoomMember.setRawDisplayName` → `RoomMember.emit
    // (RoomMemberEvent.Name, ...)`). Without the subscription a peer
    // renaming themselves stays under the old name in any list that
    // reads `useRoomMembers` (Members sheet, Settings → Members,
    // Lobby member-drawer, user-mention autocomplete). Element Web's
    // `MemberListViewModel` subscribes to the same trio.
    mx.on(RoomMemberEvent.Name, updateMemberList);
    return () => {
      disposed = true;
      mx.removeListener(RoomMemberEvent.Membership, updateMemberList);
      mx.removeListener(RoomMemberEvent.PowerLevel, updateMemberList);
      mx.removeListener(RoomMemberEvent.Name, updateMemberList);
    };
  }, [mx, roomId]);

  return members;
};
