{"size": 4009, "ext": "js", "max_stars_repo_path": "src/reducers.js", "max_stars_repo_name": "shastajs/tahoe", "max_stars_repo_stars_event_min_datetime": "2016-01-21T17:09:49.000Z", "max_stars_repo_stars_event_max_datetime": "2021-05-07T14:08:05.000Z", "max_issues_repo_path": "src/reducers.js", "max_issues_repo_name": "shastajs/tahoe", "max_issues_repo_issues_event_min_datetime": "2016-02-03T14:16:15.000Z", "max_issues_repo_issues_event_max_datetime": "2018-06-15T16:35:39.000Z", "max_forks_repo_path": "src/reducers.js", "max_forks_repo_name": "shastajs/tahoe", "max_forks_repo_forks_event_min_datetime": "2016-02-03T22:54:24.000Z", "max_forks_repo_forks_event_max_datetime": "2018-08-30T23:36:23.000Z"}
{"max_stars_count": 65, "max_issues_count": 12, "max_forks_count": 12, "avg_line_length": 32.072, "max_line_length": 93, "alphanum_fraction": 0.6355699676}
import { handleActions } from 'redux-actions'
import { OrderedMap, List, fromJS, Iterable } from 'immutable'

const toImmutable = (v) =>
  fromJS(v, (key, value) =>
    Iterable.isIndexed(value) ? value.toList() : value.toOrderedMap()
  )

const initialState = OrderedMap({
  subsets: OrderedMap()
})

// subset state
const createSubset = (state, { payload: { subset, fresh } }) => {
  if (!subset) return state
  const path = [ 'subsets', subset ]
  if (!fresh && state.hasIn(path)) return state
  const record = OrderedMap({
    id: subset,
    pending: true
  })
  return state.setIn(path, record)
}

const setSubsetData = (state, { meta: { subset }, payload: { raw, text } }) => {
  if (!subset) return state
  const path = [ 'subsets', subset ]
  if (!state.hasIn(path)) return state // subset doesnt exist
  return state.updateIn(path, (subset) =>
    subset
      .set('data', toImmutable(raw))
      .set('text', text)
      .set('pending', false)
      .set('error', null)
  )
}

const setSubsetError = (state, { meta: { subset }, payload }) => {
  if (!subset) return state
  const path = [ 'subsets', subset ]
  if (!state.hasIn(path)) return state // subset doesnt exist
  return state.updateIn(path, (subset) =>
    subset
      .delete('data')
      .delete('text')
      .set('error', payload)
      .set('pending', false)
  )
}

const setSubsetOpen = (state, { meta: { subset, collection } }) => {
  if (!subset) return state
  const path = [ 'subsets', subset ]
  if (!state.hasIn(path)) return state // subset doesnt exist
  return state.updateIn(path, (subset) =>
    subset
      .set('pending', false)
      .set('data', collection ? List() : OrderedMap())
  )
}

const insertSubsetDataItem = (state, { meta: { subset, collection }, payload: { raw } }) => {
  if (!subset) return state
  const path = [ 'subsets', subset ]
  if (!state.hasIn(path)) return state // subset doesnt exist
  const newData = toImmutable(raw)
  return state.updateIn(path, (subset) =>
    subset
      .set('pending', false)
      .update('data', (data) => {
        // first event, initialize the value
        if (data == null && collection) return List([ newData ])
        // value exists, either push or replace
        return collection ? data.push(newData) : newData
      })
  )
}

const updateSubsetDataItem = (state, { meta: { subset, collection }, payload: { raw } }) => {
  if (!subset) return state
  const path = [ 'subsets', subset ]
  if (!state.hasIn(path)) return state // subset doesnt exist
  const dataPath = [ ...path, 'data' ]
  if (!state.hasIn(dataPath)) return state // subset has no data to update
  const next = toImmutable(raw.next)
  return state.updateIn(dataPath, (data) => {
    // not a list item, replace with new value
    if (!collection) return next

    // list item, find the index and do the update
    const idx = data.findIndex((i) => i.get('id') === raw.prev.id)
    if (idx == null) return data // not our data?
    return data.set(idx, next)
  })
}
const deleteSubsetDataItem = (state, { meta: { subset, collection }, payload: { raw } }) => {
  if (!subset) return state
  const path = [ 'subsets', subset ]
  if (!state.hasIn(path)) return state // subset doesnt exist
  const dataPath = [ ...path, 'data' ]
  if (!state.hasIn(dataPath)) return state // subset has no data to update

  // not a list, just wipe the val
  if (!collection) {
    return state.removeIn(dataPath)
  }
  // item in a list, remove the specific item
  return state.updateIn(dataPath, (data) => {
    const idx = data.findIndex((i) => i.get('id') === raw.id)
    if (idx == null) return data // not our data?
    return data.delete(idx)
  })
}

// exported actions
export const api = handleActions({
  'tahoe.request': createSubset,
  'tahoe.failure': setSubsetError,
  'tahoe.success': setSubsetData,
  'tahoe.tail.open': setSubsetOpen,
  'tahoe.tail.insert': insertSubsetDataItem,
  'tahoe.tail.update': updateSubsetDataItem,
  'tahoe.tail.delete': deleteSubsetDataItem
}, initialState)
