1import * as Container from '../util/container'
2import * as Types from '../constants/types/waiting'
3import * as WaitingGen from '../actions/waiting-gen'
4import {RPCError} from '../util/errors'
5
6// set to true to see helpful debug info
7const debugWaiting = false && __DEV__
8
9const changeHelper = (
10  counts: Map<string, number>,
11  errors: Map<string, RPCError | undefined>,
12  keys: string | Array<string>,
13  diff: 1 | -1,
14  error?: RPCError
15) => {
16  getKeys(keys).forEach(k => {
17    const oldCount = counts.get(k) || 0
18    // going from 0 => 1, clear errors
19    if (oldCount === 0 && diff === 1) {
20      errors.delete(k)
21    } else {
22      if (error) {
23        errors.set(k, error)
24      }
25    }
26    const newCount = oldCount + diff
27    if (newCount === 0) {
28      counts.delete(k)
29    } else {
30      counts.set(k, newCount)
31    }
32  })
33
34  debugWaiting && console.log('DebugWaiting:', keys, new Map(counts), new Map(errors))
35}
36
37const initialState: Types.State = {
38  counts: new Map<string, number>(),
39  errors: new Map<string, RPCError>(),
40}
41
42const getKeys = (k: string | Array<string>) => {
43  if (typeof k === 'string') return [k]
44  return k
45}
46
47export default Container.makeReducer<WaitingGen.Actions, Types.State>(initialState, {
48  [WaitingGen.resetStore]: draftState => {
49    // Keep the old values else the keys will be all off and confusing
50    debugWaiting && console.log('DebugWaiting:', '*resetStore*', draftState)
51  },
52  [WaitingGen.decrementWaiting]: (draftState, action) => {
53    changeHelper(draftState.counts, draftState.errors, action.payload.key, -1, action.payload.error)
54  },
55  [WaitingGen.incrementWaiting]: (draftState, action) => {
56    changeHelper(draftState.counts, draftState.errors, action.payload.key, 1)
57  },
58  [WaitingGen.clearWaiting]: (draftState, action) => {
59    const {counts, errors} = draftState
60    debugWaiting && console.log('DebugWaiting: clear', action.payload.key)
61    getKeys(action.payload.key).forEach(key => {
62      counts.delete(key)
63      errors.delete(key)
64    })
65  },
66  [WaitingGen.batchChangeWaiting]: (draftState, action) => {
67    debugWaiting && console.log('DebugWaiting: batch', action.payload.changes)
68    action.payload.changes.forEach(({key, increment, error}) => {
69      changeHelper(draftState.counts, draftState.errors, key, increment ? 1 : -1, error)
70    })
71  },
72})
73