import { request , IRequestOptions } from "@esri/arcgis-rest-request" ; import { UserSession } from "@esri/arcgis-rest-auth" ; import { IUser , getUserUrl , joinGroup , leaveGroup } from "@esri/arcgis-rest-portal" ; import { IInitiativeModel , getProp , unique } from "@esri/hub-common" ; import { getInitiative } from "./get" ; export interface IFollowInitiativeOptions extends IRequestOptions { initiativeId : string ; authentication : UserSession ; } const getUserTag = ( initiativeId ) => `hubInitiativeId|${ initiativeId }` ; const initiativeIdFromUserTag = ( tag ) => tag . replace ( /^hubInitiativeId\|/ , "" ) ; const initiativeIdFromGroupTag = ( tag ) => tag . replace ( /^hubInitiativeFollowers\|/ , "" ) ; const getUpdateUrl = ( session ) => `${ getUserUrl ( session ) }/update` ; const currentlyFollowedInitiativesByUserTag = ( user ) : string [ ] => user . tags . map ( initiativeIdFromUserTag ) ; const currentlyFollowedInitiativesByGroupMembership = ( user ) : string [ ] => { return user . groups . map ( group => group . tags ) . reduce ( ( acc , item ) => acc . concat ( item ) , [ ] ) . filter ( tags => tags . indexOf ( "hubInitiativeFollowers|" ) === 0 ) . map ( initiativeIdFromGroupTag ) ; } ; export const currentlyFollowedInitiatives = ( user ) : string [ ] => { const byUserTags = currentlyFollowedInitiativesByUserTag ( user ) ; const byGroupMembership = currentlyFollowedInitiativesByGroupMembership ( user ) ; return [ ... byUserTags , ... byGroupMembership ] . filter ( unique ) ; } ; export const isUserFollowing = ( user , initiativeId ) : boolean => currentlyFollowedInitiatives ( user ) . indexOf ( initiativeId ) > - 1 ; /**
 * ```js
 * import { followInitiative } from "@esri/hub-initiatives";
 * //
 * followInitiative({
 *   initiativeId,
 *   authentication
 * })
 *   .then(response)
 * ```
 * Follow an initiative.
 */ export function followInitiative ( requestOptions ) { return request ( getUserUrl ( requestOptions . authentication ) , { authentication : requestOptions . authentication } ) . then ( user => { if ( isUserFollowing ( user , requestOptions . initiativeId ) ) { return Promise . reject ( `user is already following this initiative.` ) ; } return user ; } ) . then ( user => { return getInitiative ( requestOptions . initiativeId , requestOptions ) . then ( ( initiative ) => ( { user , initiative , hasFollowersGroup : false } ) ) ; } ) . then ( obj => { const groupId = getProp ( obj , "initiative.item.properties.followersGroupId" ) ; if ( groupId ) { return joinGroup ( { id : groupId , authentication : requestOptions . authentication } ) . then ( groupJoinResponse => { obj . hasFollowersGroup = groupJoinResponse . success ; return obj ; } ) ; } return obj ; } ) . then ( obj => { if ( ! obj . hasFollowersGroup ) { const tag = getUserTag ( requestOptions . initiativeId ) ; const tags = JSON . parse ( JSON . stringify ( obj . user . tags ) ) ; tags . push ( tag ) ; return request ( getUpdateUrl ( requestOptions . authentication ) , { params : { tags } , authentication : requestOptions . authentication } ) ; } return { success : true , username : obj . user . username } ; } ) ; } /**
 * ```js
 * import { unfollowInitiative } from "@esri/hub-initiatives";
 * //
 * unfollowInitiative({
 *   initiativeId,
 *   authentication
 * })
 *   .then(response)
 * ```
 * Un-follow an initiative.
 */ export function unfollowInitiative ( requestOptions ) { return request ( getUserUrl ( requestOptions . authentication ) , { authentication : requestOptions . authentication } ) . then ( user => { if ( ! isUserFollowing ( user , requestOptions . initiativeId ) ) { return Promise . reject ( `user is not following this initiative.` ) ; } return user ; } ) . then ( user => { const tag = getUserTag ( requestOptions . initiativeId ) ; const tags = JSON . parse ( JSON . stringify ( user . tags ) ) ; if ( tags . indexOf ( tag ) > - 1 ) { const index = tags . indexOf ( tag ) ; tags . splice ( index , 1 ) ; if ( tags . length === 0 ) { tags . push ( "," ) ; } return request ( getUpdateUrl ( requestOptions . authentication ) , { params : { tags } , authentication : requestOptions . authentication } ) . then ( _ => user ) ; } return user ; } ) . then ( user => { return getInitiative ( requestOptions . initiativeId , requestOptions ) . then ( ( initiative ) => ( { user , initiative } ) ) ; } ) . then ( obj => { const groupId = getProp ( obj , "initiative.item.properties.followersGroupId" ) ; if ( groupId && currentlyFollowedInitiativesByGroupMembership ( obj . user ) . indexOf ( requestOptions . initiativeId ) > - 1 ) { return leaveGroup ( { id : groupId , authentication : requestOptions . authentication } ) . then ( groupLeaveResponse => { return { success : true , username : obj . user . username } ; } ) ; } return { success : true , username : obj . user . username } ; } ) ; }