Source: app/selectors/accountStateSelectors.js

/* global WP_DEFINE_IS_NODE */
/* eslint-disable no-bitwise */
import { hasFlag } from 'common/src/app/util/bitwiseUtils';
import MemberType, {
  MemberTypeStrings,
  MemberTypeStringKeys,
} from 'common/src/app/data/enum/MemberType';
import { memberTypeSelector } from './userAccountSelectors';
import AccountState, {
  AccountStateStrings,
  accountStateTypeStrings,
} from '../data/enum/AccountState';

/**
 * Check against possible accountState flags and add them to an array if present
 * @example
 * memberFlagCheck(account.accountState);
 * @returns []
 */
export const memberFlagCheck = flag =>
  Object.values(AccountState).reduce((acc, cur) => {
    if (hasFlag(flag, cur)) {
      acc.push(AccountStateStrings[cur]);
    }
    return acc;
  }, []);

/**
 * Check a user has one specific account state
 * @param accountType one `accountStateTypeStrings` or an array of strings
 * @param state
 * @example checking if a profile is complete
 * memberIsAccountType(accountStateTypeStrings.GROUP_PROFILE_COMPLETE);
 * @returns `string` (from enum file if one result) or [array] if multiple
 * @returns {false} if no result
 */

export const memberIsAccountType = (accountTypes, accountStateValue) => {
  const accountTypeArray = typeof accountTypes === 'string' ? [accountTypes] : accountTypes;
  const accountStates = memberFlagCheck(accountStateValue);

  const results = [];

  accountTypeArray.forEach(accountType => {
    const match = accountStates.find(userAccountType => userAccountType === accountType);
    return match && results.push(match);
  });

  if (results.length === 1) {
    return String(results);
  } else if (results.length > 1) {
    return results;
  }

  return (
    new Error(`The accountTypes ${accountTypeArray} could not be found in accountState`), false
  );
};

export const groupMigrationOrMember = () => (dispatch, getState) => {
  const state = getState();

  return state.migration?.isGroupMember || memberTypeSelector(state) === MemberType.GROUP;
};

/**
 * Given a MemberType (1 || 0) will return 'group' 'online' 'public'
 */
const groupOrOnlineSelector = memberType =>
  MemberTypeStrings[MemberTypeStringKeys[memberType]] || MemberTypeStrings.PUBLIC;

export default groupOrOnlineSelector;

/**
 * DEPRECIATED: this was called groupOrOnlineSelector
 * It uses account state bitwises to determine member type, only used for new(?) authentication
 * under userPermissionState
 */
export const subscriptionTypeSelector = accountStateValue => {
  if (typeof accountStateValue !== 'number') {
    console.log('You must pass an account state number to subscriptionTypeSelector');
  }

  const hasAnyGroupFlags = !!memberIsAccountType(
    [accountStateTypeStrings.GROUP_MEMBERSHIP_VALID],
    accountStateValue,
  );

  const hasAnyOnlineFlags = !!memberIsAccountType(
    [
      accountStateTypeStrings.ONLINE_IS_MIGRATING,
      accountStateTypeStrings.ONLINE_SUBSCRIPTION_VALID,
    ],
    accountStateValue,
  );

  const hasNoFlags = !!memberIsAccountType([accountStateTypeStrings.NONE], accountStateValue);

  if (hasAnyGroupFlags) {
    return MemberTypeStrings.GROUP;
  } else if (hasAnyOnlineFlags) {
    return MemberTypeStrings.ONLINE;
  } else if (hasNoFlags) {
    return MemberTypeStrings.PUBLIC;
  }
  return MemberTypeStrings.GROUP;
};