import { actionTypes } from '../constants'

const { INIT_BY_PATH } = actionTypes

export const getWatchPath = (event, path) =>
  `${event}:${((path.substring(0, 1) === '/') ? '' : '/')}${path}`

/**
 * @description Set a new watcher
 * @param {Object} firebase - Internal firebase object
 * @param {String} event - Type of event to watch for
 * @param {String} path - Path to watch with watcher
 * @param {String} queryId - Id of query
 */
export const setWatcher = (firebase, event, path, queryId = undefined) => {
    const id = queryId || getQueryIdFromPath(path) || getWatchPath(event, path)

    if (event!='once'){
        if (firebase._.watchers[id]) {
            firebase._.watchers[id]++
        } else {
            firebase._.watchers[id] = 1
        }
    }

  return firebase._.watchers[id]
}

/**
 * @description Get count of currently attached watchers
 * @param {Object} firebase - Internal firebase object
 * @param {String} event - Type of event to watch for
 * @param {String} path - Path to watch with watcher
 * @param {String} queryId - Id of query
 */
export const getWatcherCount = (firebase, event, path, queryId = undefined) => {
  const id = queryId || getQueryIdFromPath(path) || getWatchPath(event, path)
  return firebase._.watchers[id]
}

/**
 * @description Remove/Unset a watcher
 * @param {Object} firebase - Internal firebase object
 * @param {String} event - Type of event to watch for
 * @param {String} path - Path to watch with watcher
 * @param {String} queryId - Id of query
 */
export const unsetWatcher = (firebase, dispatch, event, path, queryId = undefined) => {
  const id = queryId || getQueryIdFromPath(path) || getWatchPath(event, path)
  path = path.split('#')[0]

  if (firebase._.watchers[id] <= 1) {
    delete firebase._.watchers[id]
      if (event!='once'){
          firebase.database().ref().child(path).off(event)
          dispatch({
              type: INIT_BY_PATH,
              path
          })
      }
  } else if (firebase._.watchers[id]) {
    firebase._.watchers[id]--
  }
}

/**
 * @description Get query id from query path
 * @param {String} path - Path from which to get query id
 */
export const getQueryIdFromPath = (path) => {
    const origPath = path
    let pathSplitted = path.split('#')
    path = pathSplitted[0]

    const isQuery = pathSplitted.length > 1
    const queryParams = isQuery ? pathSplitted[1].split('&') : []
    const queryId = isQuery ? queryParams.map((param) => {
        let splittedParam = param.split('=')
        if (splittedParam[0] === 'queryId') {
            return splittedParam[1]
        }
    }).filter(q => q) : undefined
    return (queryId && queryId.length > 0)
        ? queryId[0]
        : ((isQuery) ? origPath : undefined)
}

/**
 * @description Modify query to include methods based on query parameters (such as orderByChild)
 * @param {Array} queryParams - Array of query parameters to apply to query
 * @param {Object} query - Query object on which to apply query parameters
 */
export const applyParamsToQuery = (queryParams, query) => {
  let doNotParse = false
  if (queryParams) {
    queryParams.forEach(param => {
      param = param.split('=')
      switch (param[0]) {
        case 'orderByValue':
          query = query.orderByValue()
          doNotParse = true
          break
        case 'orderByPriority':
          query = query.orderByPriority()
          doNotParse = true
          break
        case 'orderByKey':
          query = query.orderByKey()
          doNotParse = true
          break
        case 'orderByChild':
          query = query.orderByChild(param[1])
          break
        case 'limitToFirst':
          // TODO: Handle number not being passed as param
          query = query.limitToFirst(parseInt(param[1], 10))
          break
        case 'limitToLast':
          // TODO: Handle number not being passed as param
          query = query.limitToLast(parseInt(param[1], 10))
          break
        case 'equalTo':
          let equalToParam = !doNotParse ? parseInt(param[1], 10) || param[1] : param[1]
          equalToParam = equalToParam === 'null' ? null : equalToParam
          query = param.length === 3
            ? query.equalTo(equalToParam, param[2])
            : query.equalTo(equalToParam)
          break
        case 'startAt':
          let startAtParam = !doNotParse ? parseInt(param[1], 10) || param[1] : param[1]
          startAtParam = startAtParam === 'null' ? null : startAtParam
          query = param.length === 3
            ? query.startAt(startAtParam, param[2])
            : query.startAt(startAtParam)
          break
        case 'endAt':
          let endAtParam = !doNotParse ? parseInt(param[1], 10) || param[1] : param[1]
          endAtParam = endAtParam === 'null' ? null : endAtParam
          query = param.length === 3
            ? query.endAt(endAtParam, param[2])
            : query.endAt(endAtParam)
          break
      }
    })
  }

  return query
}

@@ -523,32 +523,42 @@
 nst id = queryId
++'_'+event
  %7C%7C getQueryIdFr
@@ -560,32 +560,38 @@
 yIdFromPath(path
+,event
 ) %7C%7C getWatchPat
@@ -606,16 +606,17 @@
  path)%0A%0A
+%0A
     if (
@@ -1159,32 +1159,34 @@
 undefined) =%3E %7B%0A
+  
   const id = que
@@ -1181,32 +1181,42 @@
 nst id = queryId
++'_'+event
  %7C%7C getQueryIdFr
@@ -1218,32 +1218,38 @@
 yIdFromPath(path
+,event
 ) %7C%7C getWatchPat
@@ -1263,16 +1263,18 @@
 , path)%0A
+  
   return
@@ -1639,16 +1639,18 @@
 d) =%3E %7B%0A
+  
   const 
@@ -1661,16 +1661,26 @@
  queryId
++'_'+event
  %7C%7C getQ
@@ -1698,16 +1698,22 @@
 ath(path
+,event
 ) %7C%7C get
@@ -1735,16 +1735,18 @@
 , path)%0A
+  
   path =
@@ -2242,24 +2242,40 @@
 Path = (path
+,event=undefined
 ) =%3E %7B%0A    c
@@ -2750,24 +2750,33 @@
 0)%0A        ?
+ (event ?
  queryId%5B0%5D%0A
@@ -2774,16 +2774,40 @@
 eryId%5B0%5D
++'_'+event : queryId%5B0%5D)
 %0A       

add event to queued for watchers