import {update_item, update_items, remove_item, store_items, filter_items} from './base'
import moment from 'common/moment'
import {
  set_from_array,
  hash_with_key,
  group_hash_by_value,
  set_union,
  array_from_set,
  filter_hash,
  create_hash,
  property_getter,
  flatten_array,
} from 'common/utilities'

const initial_state = {
  deals: {},
  missions: {},
  events: {},
  idGenerator: 0,
  users: {},
  workplaces: {},
  missions_loaded: false,
}

const update_users_status = (state, mission_id, user_ids, status) => {
  let mission_users = {
    ...(state.users[mission_id] || {}),
    ...create_hash(user_ids, () => status),
  }
  return {
    ...state,
    users: {
      ...state.users,
      [mission_id]: mission_users,
    },
  }
}

const store_missions = (state, missions) => ({
  ...state,
  missions: missions.reduce((missions, mission) => ({
    ...missions,
    [mission.id]: {
      ...mission,
    },
  }), state.missions),
  events: missions.reduce((events, mission) => ({
    ...events,
    ...hash_with_key(mission.events),
  }), state.events),
  users: missions.reduce((users, mission) => ({
    ...users,
    [mission.id]: mission.users_status,
  }), state.users),
  missions_loaded: true,
})

const update_mission = (state, mission) => {
  let {id, users_status, events} = mission
  return update_item(
    store_items(
      users_status ? {
        ...state,
        users: {
          ...state.users,
          [id]: users_status
        }
      } : state,
      "events",
      events,
    ),
    "missions",
    mission
  )
}

const store_deals = (state, deals) => store_items(
  store_missions(
    state,
    flatten_array(deals.map(({template_mission, missions}) => [template_mission, ...(missions || [])].filter(Boolean)))
  ),
  "deals",
  deals.map(sanitize_deal)
)

const sanitize_deal = ({template_mission, custom_field_ids, ...deal}) => {
  deal = {...deal}
  if (template_mission) {
    deal['template_mission_id'] = template_mission.id
  }
  if (custom_field_ids) {
    deal['custom_field_ids'] = Array.isArray(custom_field_ids) ? set_from_array(custom_field_ids) : custom_field_ids
  }
  return deal
}

function remove_deal(state, id) {
  return update_item(state, "deals", {id, deleted_at: moment()})
}

export function missions(state = initial_state, action) {
  let events, user_ids, mission
  switch (action.type) {
    case "store_missions":
      return store_missions(state, action.missions)
    case "update_mission":
      return update_mission(state, action.mission)
    case "update_missions":
      return action.missions.reduce(update_mission, state)
    case "store_mission_events":
      return store_items(state, "events", action.events)
    case "replace_mission_events":
      return store_items(
        filter_items(state, "events", ({calenderable_id}) => calenderable_id != action.mission_id),
        "events",
        action.events
      )
    case "remove_mission":
      return remove_item(state, "missions", action.mission_id)
    case "update_mission_event":
      events = {...state.events}
      delete events[action.temp_id]
      return {
        ...state,
        events: {
          ...events,
          [action.mission_event.id]: action.mission_event,
        },
      }
    case "send_mission":
      return update_users_status(state, action.mission_id, action.user_ids, "new")
    case "assign_mission":
      return update_users_status(state, action.mission_id, action.user_ids, "assigned")
    case "unassign_mission":
      return update_users_status(state, action.mission_id, action.user_ids, "accepted")
    case "store_workplaces":
      return store_items(state, "workplaces", action.workplaces)
    case "update_workplace":
      return update_item(state, "workplaces", action.workplace)
    case "update_workplaces":
      return update_items(state, "workplaces", action.workplaces)
    case "store_recruiters":
      return store_deals(state, action.recruiters.map(property_getter('default_deal')))
    case "store_deals":
    case "update_deals":
      return store_deals(state, action.deals)
    case "update_deal":
      return store_deals(state, [action.deal])
    case "remove_deal":
      return remove_deal(state, action.deal_id)
    case "remove_deals":
      return action.deal_ids.reduce((state, deal_id) => remove_deal(state, deal_id), state)
    default:
      return state
  }
}
