import {browserHistory} from 'react-router'
import store from 'common/store'
import Channel, {init_websocket} from 'common/channel'
import request from 'common/request'
import {array_contains, split_array, property_getter, empty_array} from 'common/utilities'
import {action_logout} from 'common/authentication'
import {update_profile} from 'actions/profile'
import {store_messages, create_message} from 'actions/messages'
import {store_muted_users, store_muting_recruiters} from 'actions/mutes'
import {store_users, store_recruiter_users, update_users} from 'actions/users'
import {
  store_missions, update_missions, store_workplaces, update_workplaces, store_mission_events,
  store_deals, update_deals, remove_deal,
} from 'actions/missions'
import {store_recruiters, update_recruiters, store_teams, remove_team} from 'actions/recruiters'
import {alert_info} from 'actions/display'
import {store_fields, update_fields, update_values, remove_value, remove_field} from 'actions/fields'
import {store_events, remove_event} from 'actions/calendar'
import {store_demands} from 'actions/demands'
import {store_shifts, store_shift_events} from 'actions/shifts'
import {get_users} from 'selectors/users'

const recruiter_requests = (recruiter_id, dispatch) => {
  request.get(`recruiters/${recruiter_id}/recipients`)
  .then((users) => dispatch(store_recruiter_users(users.map((user) => user.id))))

  request.get(`recruiters/${recruiter_id}/muted_users`)
  .then((muted_users) => dispatch(store_muted_users(muted_users.map((user) => user.id))))

  request.get(`recruiters/${recruiter_id}`)
  .then((recruiter) => {
    dispatch(update_profile(recruiter))
    if (!recruiter.first_name || recruiter.first_name == "" || !recruiter.last_name || recruiter.last_name == "") {
      dispatch(alert_info("Veuillez renseigner votre prénom et nom."))
      browserHistory.push(`/settings`)
    }
  })

  request.get(`recruiters/${recruiter_id}/last_messages`)
  .then((messages) => dispatch(store_messages(messages)))

  request.get(`recruiters/${recruiter_id}/unread_messages`)
  .then((messages) => dispatch(store_messages(messages)))

  request.get(`recruiters/${recruiter_id}/demands`)
  .then((demands) => dispatch(store_demands(demands)))

  request.get(`recruiters/${recruiter_id}/applied_users`)
  .then((users) => dispatch(store_users(users)))
}

const agency_requests = (agency_id, dispatch) => {
  request.get_paginated(`agencies/${agency_id}/deals`, {}, (deals) => dispatch(store_deals(deals)))

  request.get(`agencies/${agency_id}/fields`)
  .then((fields) => dispatch(store_fields(fields)))

  request.get(`agencies/${agency_id}/workplaces`)
  .then((workplaces) => dispatch(store_workplaces(workplaces)))

  request.get(`agencies/${agency_id}/recruiters`)
  .then((recruiters) => dispatch(store_recruiters(recruiters)))

  request.get(`agencies/${agency_id}/teams`)
  .then((teams) => dispatch(store_teams(teams)))

  request.get_paginated(`agencies/${agency_id}/users`, {}, (users) => dispatch(store_users(users)))
}

const agency_channel = (recruiter_id, dispatch) => {
  const channel = new Channel("RecruiterAgency")

  channel.register('create_message', (message) => {
    let state = store.getState()
    dispatch(store_messages([message]))

    request.get(`recruiters/${recruiter_id}/recipients`)
    .then((users) => {
      users = users.map((user) => user.id)
      if (message.sender_type == 'User' && array_contains(users, message.sender_id)) {
        let p = new Promise((resolve, reject) => {
          if (window.Notification) {
            if (window.Notification.permission === "granted") {
              resolve()
            } else if (window.Notification.permission !== "denied") {
              window.Notification.requestPermission((status) => {
                if (status === "granted") {
                  resolve()
                } else {
                  reject()
                }
              })
            } else {
              reject()
            }
          } else {
            reject()
          }
        }).then(() => {
          let {full_name} = get_users(state)[message.sender_id]
          let n = new Notification(full_name, {body: message.content})
          setTimeout(n.close.bind(n), 5000)
        })
      }
      dispatch(store_recruiter_users(users))
    })
  })

  if (window.Notification) {
    if (window.Notification.permission !== "granted") {
      let Notification = window.Notification
      Notification.requestPermission((status) => {
        if (Notification.permission !== status) {
          Notification.permission = status
        }
      })
    }
  } else {
    dispatch(alert_info("Votre navigateur ne vous permet pas de recevoir des notifications pour les nouveaux messages des candidats. Veuillez utiliser Chrome."))
  }

  channel.register_store('event', (events) => {
    const {User, UserAgency, Mission, Shift} = split_array(
      events,
      property_getter('calenderable_type'),
      ['User', 'UserAgency', 'Mission', 'Shift']
    )
    const user_events = [...User, ...UserAgency]
    if (!empty_array(user_events)) {
      dispatch(store_events(user_events))
    }
    if (!empty_array(Mission)) {
      dispatch(store_mission_events(Mission))
    }
    if (!empty_array(Shift)) {
      dispatch(store_shift_events(Shift))
    }
  })
  channel.register_store('message', (messages) => dispatch(store_messages(messages)))
  channel.register_store('user', (users) => dispatch(update_users(users)))
  channel.register_store('user_agency', (users) => dispatch(update_users(users)))
  channel.register_store('mission', (missions) => dispatch(update_missions(missions)))
  channel.register_store('deal', (deals) => dispatch(update_deals(deals)))
  channel.register_store('workplace', (workplaces) => dispatch(update_workplaces(workplaces)))
  channel.register_store('recruiter', (recruiters) => dispatch(update_recruiters(recruiters)))
  channel.register_store('agency', ([agency]) => dispatch(update_profile({agency})))
  channel.register_store('field', (fields) => dispatch(update_fields(fields)))
  channel.register_store('value', (values) => dispatch(update_values(values)))
  channel.register_store('demand', (demands) => dispatch(store_demands(demands)))
  channel.register_store('shift', (shifts) => dispatch(store_shifts(shifts)))
  channel.register_store('team', (teams) => dispatch(store_teams(teams)))
  channel.register_destroy('team', (team_id) => dispatch(remove_team(team_id)))
}

export default () => {
  const dispatch = store.dispatch

  request.get(`profile`)
  .then((profile) => {
    dispatch(update_profile(profile))
    const recruiter_id = store.getState().profile.id
    const {token} = store.getState().authentication

    recruiter_requests(recruiter_id, dispatch)

    return request.get(`recruiters/${recruiter_id}/agency`)
    .then((agency) => {
      dispatch(update_profile({agency}))
      const state = store.getState()
      const agency_id = state.profile.agency.id

      agency_requests(agency_id, dispatch)

      init_websocket({client_type: 'recruiter', id: recruiter_id, auth_token: window.btoa(token)})
      agency_channel(recruiter_id, dispatch)
    })
  }, action_logout)
}
