docs: private boolean updateState(ImmutableMember member) {
      // If the member matches the local member, ignore the update.
      if (member.id().equals(localMember.id())) {
        return false;
      }
  
      SwimMember swimMember = members.get(member.id());
  
      // If the local member is not present, add the member in the ALIVE state.
      if (swimMember == null) {
        if (member.state() == State.ALIVE) {
          swimMember = new SwimMember(member);
          members.put(swimMember.id(), swimMember);
          randomMembers.add(swimMember);
          Collections.shuffle(randomMembers);
          LOGGER.debug("{} - Member added {}", this.localMember.id(), swimMember);
          swimMember.setState(State.ALIVE);
          post(new GroupMembershipEvent(GroupMembershipEvent.Type.MEMBER_ADDED, swimMember.copy()));
          recordUpdate(swimMember.copy());
          return true;
        }
        return false;
      }
      // If the term has been increased, update the member and record a gossip event.
      else if (member.incarnationNumber() > swimMember.getIncarnationNumber()) {
        // If the member's version has changed, remove the old member and add the new member.
        if (!Objects.equals(member.version(), swimMember.version())) {
          members.remove(member.id());
          randomMembers.remove(swimMember);
          post(new GroupMembershipEvent(GroupMembershipEvent.Type.MEMBER_REMOVED, swimMember.copy()));
          swimMember = new SwimMember(member);
          swimMember.setState(State.ALIVE);
          members.put(member.id(), swimMember);
          randomMembers.add(swimMember);
          Collections.shuffle(randomMembers);
          LOGGER.debug("{} - Evicted member for new version {}", this.localMember.id(), swimMember);
          post(new GroupMembershipEvent(GroupMembershipEvent.Type.MEMBER_ADDED, swimMember.copy()));
          recordUpdate(swimMember.copy());
        } else {
          // Update the term for the local member.
          swimMember.setIncarnationNumber(member.incarnationNumber());
  
          // If the state has been changed to ALIVE, trigger a REACHABILITY_CHANGED event and then update metadata.
          if (member.state() == State.ALIVE && swimMember.getState() != State.ALIVE) {
            swimMember.setState(State.ALIVE);
            LOGGER.debug("{} - Member reachable {}", this.localMember.id(), swimMember);
            post(new GroupMembershipEvent(GroupMembershipEvent.Type.REACHABILITY_CHANGED, swimMember.copy()));
            if (!Objects.equals(member.properties(), swimMember.properties())) {
              swimMember.properties().putAll(member.properties());
              LOGGER.debug("{} - Member metadata changed {}", this.localMember.id(), swimMember);
              post(new GroupMembershipEvent(GroupMembershipEvent.Type.METADATA_CHANGED, swimMember.copy()));
            }
          }
          // If the state has been changed to SUSPECT, update metadata and then trigger a REACHABILITY_CHANGED event.
          else if (member.state() == State.SUSPECT && swimMember.getState() != State.SUSPECT) {
            if (!Objects.equals(member.properties(), swimMember.properties())) {
              swimMember.properties().putAll(member.properties());
              LOGGER.debug("{} - Member metadata changed {}", this.localMember.id(), swimMember);
              post(new GroupMembershipEvent(GroupMembershipEvent.Type.METADATA_CHANGED, swimMember.copy()));
            }
            swimMember.setState(State.SUSPECT);
            LOGGER.debug("{} - Member unreachable {}", this.localMember.id(), swimMember);
            post(new GroupMembershipEvent(GroupMembershipEvent.Type.REACHABILITY_CHANGED, swimMember.copy()));
            if (config.isNotifySuspect()) {
              gossip(swimMember, Lists.newArrayList(swimMember.copy()));
            }
          }
          // If the state has been changed to DEAD, trigger a REACHABILITY_CHANGED event if necessary and then remove
          // the member from the members list and trigger a MEMBER_REMOVED event.
          else if (member.state() == State.DEAD && swimMember.getState() != State.DEAD) {
            if (swimMember.getState() == State.ALIVE) {
              swimMember.setState(State.SUSPECT);
              LOGGER.debug("{} - Member unreachable {}", this.localMember.id(), swimMember);
              post(new GroupMembershipEvent(GroupMembershipEvent.Type.REACHABILITY_CHANGED, swimMember.copy()));
            }
            swimMember.setState(State.DEAD);
            members.remove(swimMember.id());
            randomMembers.remove(swimMember);
            Collections.shuffle(randomMembers);
            LOGGER.debug("{} - Member removed {}", this.localMember.id(), swimMember);
            post(new GroupMembershipEvent(GroupMembershipEvent.Type.MEMBER_REMOVED, swimMember.copy()));
          } else if (!Objects.equals(member.properties(), swimMember.properties())) {
            swimMember.properties().putAll(member.properties());
            LOGGER.debug("{} - Member metadata changed {}", this.localMember.id(), swimMember);
            post(new GroupMembershipEvent(GroupMembershipEvent.Type.METADATA_CHANGED, swimMember.copy()));
          }
  
          // Always enqueue an update for gossip when the term changes.
          recordUpdate(swimMember.copy());
          return true;
        }
      }
      // If the term remained the same but the state has progressed, update the state and trigger events.
      else if (member.incarnationNumber() == swimMember.getIncarnationNumber() && member.state().ordinal() > swimMember.getState().ordinal()) {
        swimMember.setState(member.state());
  
        // If the updated state is SUSPECT, post a REACHABILITY_CHANGED event and record an update.
        if (member.state() == State.SUSPECT) {
          LOGGER.debug("{} - Member unreachable {}", this.localMember.id(), swimMember);
          post(new GroupMembershipEvent(GroupMembershipEvent.Type.REACHABILITY_CHANGED, swimMember.copy()));
          if (config.isNotifySuspect()) {
            gossip(swimMember, Lists.newArrayList(swimMember.copy()));
          }
        }
        // If the updated state is DEAD, post a REACHABILITY_CHANGED event if necessary, then post a MEMBER_REMOVED
        // event and record an update.
        else if (member.state() == State.DEAD) {
          members.remove(swimMember.id());
          randomMembers.remove(swimMember);
          Collections.shuffle(randomMembers);
          LOGGER.debug("{} - Member removed {}", this.localMember.id(), swimMember);
          post(new GroupMembershipEvent(GroupMembershipEvent.Type.MEMBER_REMOVED, swimMember.copy()));
        }
        recordUpdate(swimMember.copy());
        return true;
      }
      return false;
    }