function Cerebro({
  results, selected, visibleResults, actions, term, prevTerm, statusBarText
}) {
  const mainInput = useRef(null)
  const [mainInputFocused, setMainInputFocused] = useState(false)
  const [prevResultsLenght, setPrevResultsLenght] = useState(() => results.length)

  const focusMainInput = () => {
    mainInput.current.focus()
    if (config.get('selectOnShow')) {
      mainInput.current.select()
    }
  }

  // suscribe to events
  useEffect(() => {
    focusMainInput()
    updateElectronWindow(results, visibleResults)
    // Listen for window.resize and change default space for results to user's value
    window.addEventListener('resize', onWindowResize)
    // Add some global key handlers
    window.addEventListener('keydown', onDocumentKeydown)
    // Cleanup event listeners on unload
    // NOTE: when page refreshed (location.reload) componentWillUnmount is not called
    window.addEventListener('beforeunload', cleanup)
    electronWindow.on('show', focusMainInput)
    electronWindow.on('show', () => updateElectronWindow(results, visibleResults))

    // function to be called when unmounted
    return () => {
      cleanup()
    }
  }, [])

  if (results.length !== prevResultsLenght) {
    // Resize electron window when results count changed
    updateElectronWindow(results, visibleResults)
    setPrevResultsLenght(results.length)
  }

  /**
   * Handle resize window and change count of visible results depends on window size
   */
  const onWindowResize = () => {
    if (results.length <= MIN_VISIBLE_RESULTS) return false

    let maxVisibleResults = Math.floor((window.outerHeight - INPUT_HEIGHT) / RESULT_HEIGHT)
    maxVisibleResults = Math.max(MIN_VISIBLE_RESULTS, maxVisibleResults)
    if (maxVisibleResults !== visibleResults) {
      actions.changeVisibleResults(maxVisibleResults)
    }
  }

  /**
   * Handle keyboard shortcuts
   */
  const onKeyDown = (event) => {
    const highlighted = highlightedResult()
    // TODO: go to first result on cmd+up and last result on cmd+down
    if (highlighted && highlighted.onKeyDown) highlighted.onKeyDown(event)

    if (event.defaultPrevented) { return }

    const keyActions = {
      select: () => selectCurrent(event),

      arrowRight: () => {
        if (cursorInEndOfInut(event.target)) {
          if (autocompleteValue()) {
            // Autocomplete by arrow right only if autocomple value is shown
            autocomplete(event)
          } else {
            focusPreview()
            event.preventDefault()
          }
        }
      },

      arrowDown: () => {
        actions.moveCursor(1)
        event.preventDefault()
      },

      arrowUp: () => {
        if (results.length > 0) {
          actions.moveCursor(-1)
        } else if (prevTerm) {
          actions.updateTerm(prevTerm)
        }
        event.preventDefault()
      }
    }

    // shortcuts for ctrl+...
    if ((event.metaKey || event.ctrlKey) && !event.altKey) {
      // Copy to clipboard on cmd+c
      if (event.keyCode === 67) {
        const text = highlightedResult()?.clipboard || term
        if (text) {
          clipboard.writeText(text)
          actions.reset()
          if (!event.defaultPrevented) {
            electronWindow.hide()
          }
          event.preventDefault()
        }
        return
      }

      // Select text on cmd+a
      if (event.keyCode === 65) {
        mainInput.current.select()
        event.preventDefault()
      }

      // Select element by number
      if (event.keyCode >= 49 && event.keyCode <= 57) {
        const number = Math.abs(49 - event.keyCode)
        const result = results[number]

        if (result) return selectItem(result, event)
      }

      // Lightweight vim-mode: cmd/ctrl + jklo
      switch (event.keyCode) {
        case 74:
          keyActions.arrowDown()
          break
        case 75:
          keyActions.arrowUp()
          break
        case 76:
          keyActions.arrowRight()
          break
        case 79:
          keyActions.select()
          break
      }
    }

    switch (event.keyCode) {
      case 9:
        autocomplete(event)
        break
      case 39:
        keyActions.arrowRight()
        break
      case 40:
        keyActions.arrowDown()
        break
      case 38:
        keyActions.arrowUp()
        break
      case 13:
        keyActions.select()
        break
      case 27:
        actions.reset()
        electronWindow.hide()
        break
    }
  }

  const onMainInputFocus = () => setMainInputFocused(true)
  const onMainInputBlur = () => setMainInputFocused(false)

  const cleanup = () => {
    window.removeEventListener('resize', onWindowResize)
    window.removeEventListener('keydown', onDocumentKeydown)
    window.removeEventListener('beforeunload', cleanup)
    electronWindow.removeAllListeners('show')
  }

  /**
   * Get highlighted result
   * @return {Object}
   */
  const highlightedResult = () => results[selected]

  /**
   * Select item from results list
   * @param  {[type]} item [description]
   * @return {[type]}      [description]
   */
  const selectItem = (item, realEvent) => {
    actions.reset()
    const event = wrapEvent(realEvent)
    item.onSelect(event)

    if (!event.defaultPrevented) electronWindow.hide()
  }

  /**
   * Autocomple search term from highlighted result
   */
  const autocomplete = (event) => {
    const { term: highlightedTerm } = highlightedResult()
    if (highlightedTerm && highlightedTerm !== term) {
      actions.updateTerm(highlightedTerm)
      event.preventDefault()
    }
  }

  /**
   * Select highlighted element
   */
  const selectCurrent = (event) => selectItem(highlightedResult(), event)

  const autocompleteValue = () => {
    const selectedResult = highlightedResult()
    if (selectedResult && selectedResult.term) {
      const regexp = new RegExp(`^${escapeStringRegexp(term)}`, 'i')
      if (selectedResult.term.match(regexp)) {
        return selectedResult.term.replace(regexp, term)
      }
    }
    return ''
  }

  return (
    <div className={styles.search}>
      <Autocomplete autocompleteCalculator={autocompleteValue} />
      <div className={styles.inputWrapper}>
        <input
          placeholder={config.get('searchBarPlaceholder')}
          type="text"
          id="main-input"
          ref={mainInput}
          value={term}
          className={styles.input}
          onChange={(e) => actions.updateTerm(e.target.value)}
          onKeyDown={onKeyDown}
          onFocus={onMainInputFocus}
          onBlur={onMainInputBlur}
        />
      </div>
      <ResultsList
        results={results}
        selected={selected}
        visibleResults={visibleResults}
        onItemHover={actions.selectElement}
        onSelect={selectItem}
        mainInputFocused={mainInputFocused}
      />
      {statusBarText && <StatusBar value={statusBarText} />}
    </div>
  )
}
Main search container

TODO: Remove redux
TODO: Split to more components