/** @module SZTMExcel */

// Import dependencies
import React from 'react'
import ReactDOM from 'react-dom'
import { createStore, applyMiddleware, combineReducers, bindActionCreators, compose } from 'redux'
import { Provider, connect } from 'react-redux'
import createSagaMiddleware from 'redux-saga'
import { all } from 'redux-saga/effects'
import SockJS from 'sockjs-client'
import { SZTM_API } from './local-constants'

// React router
import { createBrowserHistory } from 'history'
import { ConnectedRouter, connectRouter, routerMiddleware } from 'connected-react-router'
 
// Import the main app
import Main from './Main'

// Import the submodules
import api from './api'
import layout from './layout'
import alerts from './alerts'
import users from './users'
import config from './config'
import sms from './sms'
import swisstennis from './swisstennis'
import sztm from './sztm'

const socketClient = new SockJS(`${SZTM_API}/socket`)
socketClient.onopen = () => {
  console.log('Connection open', socketClient.protocol)
}
socketClient.onmessage = (message) => {
  console.log('Connection message', message.data)
}
socketClient.onclose = () => {
  console.log('Connection closed')
}
console.log(socketClient)

/** 
 * Browser History
 */
const history = createBrowserHistory()
console.log('history:', history)

/**
 * Redux Section
 */

/** The root reducer is combined from all sub-module reducers */
const rootReducer = combineReducers({
  api: api.reducer,
  layout: layout.reducer,
  alerts: alerts.reducer,
  users: users.reducer,
  config: config.reducer,
  swisstennis: swisstennis.reducer,
  sztm: sztm.reducer,
  sms: sms.reducer
})
console.log('Root reducer:', rootReducer)

/** The default state is combined from all sub-module states */
const defaultState = {
  api: api.state,
  layout: layout.state,
  alerts: alerts.state,
  users: users.state,
  config: config.state,
  swisstennis: swisstennis.state,
  sztm: sztm.state,
  sms: sms.state
}
console.log('Default state:', defaultState)

/** The root saga, calling all other sagas */
function * rootSaga () {
  console.log('rootSaga called')
  yield all([
    api.saga(),
    layout.saga(),
    alerts.saga(),
    users.saga(),
    config.saga(),
    swisstennis.saga(),
    sztm.saga(),
    sms.saga()
  ])
}

/** Create the saga middleware */
const sagaMiddleware = createSagaMiddleware()

const logger = store => next => action => {
  console.log('dispatching', action)
  let result = next(action)
  console.log('next state', store.getState())
  return result
}

const crashReporter = store => next => action => {
  try {
    return next(action)
  } catch (err) {
    console.error('Caught an exception!', err)
    throw err
  }
}

const middleware = [
  logger,
  crashReporter,
  alerts.middleware,
  sagaMiddleware,
  routerMiddleware(history)
]
/** The enhancer allows to use Redux development tools in Chrome */
// see: https://github.com/zalmoxisus/redux-devtools-extension/issues/220
let enhancer
if (window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) {
  enhancer = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__(
    applyMiddleware(...middleware)
  )
} else {
  enhancer = compose(
    applyMiddleware(...middleware)
  )
}
// const enhancer = compose(
//   applyMiddleware(alerts.middleware),
//   applyMiddleware(sagaMiddleware),
//   applyMiddleware(logger),
//   applyMiddleware(crashReporter),
//   window.devToolsExtension ? window.devToolsExtension() : f => f
// )
console.log('Enhancers:', enhancer)

/** Build the Redux store from the rootReducer, the defualtState and the enhancers. */
const store = createStore(connectRouter(history)(rootReducer), defaultState, enhancer)
console.log('Store:', store)
sagaMiddleware.run(rootSaga)

/** Collect the action creators from all modules in actionCreators */
const actionCreators = {
  api: api.actions,
  layout: layout.actions,
  alerts: alerts.actions,
  users: users.actions,
  config: config.actions,
  swisstennis: swisstennis.actions,
  sztm: sztm.actions,
  sms: sms.actions
}

/** Creates a function  */
function mapStateToProps (state) {
  const propState = {}
  Object.keys(state).forEach(key => {
    propState[key] = state[key]
  })
  console.log('Mapping state to props:', state, propState)
  return propState
}

function mapDispatchToProps (dispatch) {
  const boundActionCreators = {}
  console.log('ActionCreators', actionCreators)
  Object.keys(actionCreators).forEach(key => {
    boundActionCreators[`${key}Actions`] = bindActionCreators(actionCreators[key], dispatch)
  })
  console.log('Mapping dispatch to props:', dispatch, boundActionCreators)
  return boundActionCreators
}

const App = connect(mapStateToProps, mapDispatchToProps)(Main)

/**
 * React-Router Section
 **/

// Combine the routes from all modules.
const router = (
  <Provider store={store}>
    <ConnectedRouter history={history}>
      <App />
    </ConnectedRouter>
  </Provider>
)

/**
 * Render the app
 **/
ReactDOM.render(
  router,
  document.getElementById('root')
)


/* Hot module reloading
if (module.hot) {
  module.hot.accept('./Main', () => {
    render()
  })

  module.hot.accept('./reducers', () => {
    store.replaceReducer(connectedRouter(history)(rootReducer))
  })
}*/