{"size": 4214, "ext": "js", "max_stars_repo_path": "src/common/chat/actions.js", "max_stars_repo_name": "FredLabelle/chatx-efounders", "max_stars_repo_stars_event_min_datetime": null, "max_stars_repo_stars_event_max_datetime": null, "max_issues_repo_path": "src/common/chat/actions.js", "max_issues_repo_name": "FredLabelle/chatx-efounders", "max_issues_repo_issues_event_min_datetime": null, "max_issues_repo_issues_event_max_datetime": null, "max_forks_repo_path": "src/common/chat/actions.js", "max_forks_repo_name": "FredLabelle/chatx-efounders", "max_forks_repo_forks_event_min_datetime": null, "max_forks_repo_forks_event_max_datetime": null}
{"max_stars_count": null, "max_issues_count": null, "max_forks_count": null, "avg_line_length": 27.5424836601, "max_line_length": 100, "alphanum_fraction": 0.6312292359}
// @flow
import type { Action, Deps, Room, Message } from '../types';
import { Observable } from 'rxjs/Observable';
import { range } from 'ramda';
import { appError } from '../app/actions';

export const createRoom = (title: string) =>
({ getUid, now, firebase }: Deps): Action => {
  return {
    type: 'CREATE_ROOM',
    payload: {
      createdAt: now(),
      title: title.trim(),
    }
  }
};

export const roomCreated = (): Action => ({
  type: 'ROOM_CREATED'
});

export const selectRoom = (roomId: string) : Action => ({
  type: 'SELECT_ROOM',
  payload: { roomId },
});

export const joinRoom = (roomId: string, user: User) : Action => {
  return {
    type: 'JOIN_ROOM',
    payload: {
      roomId: roomId,
      user: user,
    },
  }
};

export const leaveRoom = (roomId: string, userId: string) : Action => ({
  type: 'LEAVE_ROOM',
  payload: {
    roomId: roomId,
    userId: userId,
  },
});

export const sendMessage = (title: string, user: User, roomId: string) =>
({ now }: Deps): Action => ({
  type: 'SEND_MESSAGE',
  payload: {
    message: {
      text: title.trim(),
      createdAt: now(),
      roomId: roomId,
      authorId: user.id,
      authorName: user.displayName,
    },
  },
});

export const messageSent = (messageId: string): Action => {
    return  {
      type: 'MESSAGE_SENT',
      payload: {
        messageId: messageId,
      }
    }
};

export const fetchRooms = (): Action => {
  //TODO implement loader on view
  return {
    type: 'FETCH_ROOMS',
  };
};

export const roomsFetched = (snap: Object): Action => {
  const rooms = snap.val();
  return {
    type: 'ROOMS_FETCHED',
    payload: { rooms },
  };
};

export const roomFetched = (snap: Object): Action => {
  const room = snap.val();
  return {
    type: 'ROOM_FETCHED',
    payload: { room },
  };
};

export const userJoinedRoom = (): Action => {
  return {
    type: 'USER_JOINED_ROOM',
  };
};

export const userLeftRoom = (): Action => {
  return {
    type: 'USER_LEFT_ROOM',
  };
};

const createRoomEpic = (action$: any, { firebase }: Deps) =>
  action$.filter((action: Action) => action.type === 'CREATE_ROOM')
  .mergeMap(action => {
    const promise = firebase.child(`rooms/`).push(action.payload);
    return Observable.from(promise)
    .map(() => promise.update({id: promise.key}))//add firebase generated ID inside the object
    .map(roomCreated)
    .catch(error => Observable.of(appError(error)));
});

const saveMessageEpic = (action$: any, { firebase }: Deps) =>
  action$.filter((action: Action) => action.type === 'SEND_MESSAGE')
  .mergeMap(action => {
    let ref = firebase.child(`rooms/${action.payload.message.roomId}/messages`)
    const promise = ref.push(action.payload.message);
    return Observable.from(promise)
    .map(() => promise.update({id: promise.key}))//add firebase generated ID inside the object
    .mapTo(messageSent(promise.key))
    .catch(error => Observable.of(appError(error)));
});

const selectRoomEpic = (action$: any, { firebase }: Deps) =>
  action$.filter((action: Action) => action.type === 'SELECT_ROOM')
  .mergeMap(action => {
    let ref = firebase.child(`rooms/${action.payload.roomId}`).on("value", roomFetched)
    return Observable.of();
});

const joinRoomEpic = (action$: any, { firebase }: Deps) =>
  action$.filter((action: Action) => action.type === 'JOIN_ROOM')
  .mergeMap(action => {
    let ref = firebase.child(`rooms/${action.payload.roomId}/members/${action.payload.user.id}`)
    const promise = ref.push({ user: action.payload.user});
    return Observable.from(promise)
    .mapTo(userJoinedRoom())
    .catch(error => Observable.of(appError(error)));
});

const leaveRoomEpic = (action$: any, { firebase }: Deps) =>
  action$.filter((action: Action) => action.type === 'LEAVE_ROOM')
  .mergeMap(action => {
    let ref = firebase.child(`rooms/${action.payload.roomId}/members/${action.payload.userId}`)
    const promise = ref.remove();
    //TODO stop listenning to firebase room update after leaving
    return Observable.from(promise)
    .mapTo(userLeftRoom())
    .catch(error => Observable.of(appError(error)));
});

export const epics = [createRoomEpic, saveMessageEpic, selectRoomEpic, joinRoomEpic, leaveRoomEpic];
