import {
  DEFAULT_PAGE_PROPS,
  DEFAULT_SEARCH_PROPS,
  setPageProps,
  setPagination,
  setSearchProps
} from "actions"
import NotFound from "components/NotFound"
import _isEmpty from "lodash/isEmpty"
import PropTypes from "prop-types"
import React, { useEffect } from "react"
import { hideLoading, showLoading } from "react-redux-loading-bar"
import { animateScroll, Link } from "react-scroll"

export const mapDispatchToProps = (dispatch, ownProps) => ({
  showLoading: () => dispatch(showLoading()),
  hideLoading: () => dispatch(hideLoading()),
  setPageProps: pageProps => dispatch(setPageProps(pageProps)),
  setSearchProps: searchProps => dispatch(setSearchProps(searchProps)),
  setPagination: (pageKey, pageNum) => dispatch(setPagination(pageKey, pageNum))
})

export const routerRelatedPropTypes = {
  location: PropTypes.object,
  history: PropTypes.object.isRequired
}

export const propTypes = {
  showLoading: PropTypes.func.isRequired,
  hideLoading: PropTypes.func.isRequired,
  setPageProps: PropTypes.func.isRequired,
  setSearchProps: PropTypes.func.isRequired,
  searchQuery: PropTypes.shape({
    text: PropTypes.string,
    filters: PropTypes.any,
    objectType: PropTypes.string
  }),
  ...routerRelatedPropTypes
}

export const AnchorLink = function(props) {
  const { to, children, ...remainingProps } = props
  return (
    <Link
      to={to}
      smooth
      duration={500}
      containerId="main-viewport"
      {...remainingProps}
    >
      {props.children}
    </Link>
  )
}

AnchorLink.propTypes = {
  to: PropTypes.string,
  children: PropTypes.node
}

export function jumpToTop() {
  animateScroll.scrollToTop({
    duration: 500,
    delay: 100,
    smooth: "easeInOutQuint",
    containerId: "main-viewport"
  })
}

export const useBoilerplate = props => {
  useEffect(
    () => {
      applyPageProps(props.setPageProps, props.pageProps)
      applySearchProps(props.setSearchProps, props.searchProps)
    },
    [] // eslint-disable-line react-hooks/exhaustive-deps
  )
  useEffect(
    () => toggleLoading(props.loading, props.showLoading, props.hideLoading),
    [props.loading] // eslint-disable-line react-hooks/exhaustive-deps
  )
  if (props.loading) {
    return { done: true, result: <span className="loading">Loading…</span> }
  }
  if (props.error) {
    return {
      done: true,
      result: renderError(props.error, props.modelName, props.uuid)
    }
  }
  return { done: false }
}

export const renderError = (error, modelName, uuid) => {
  if (error.status === 404) {
    const text = modelName ? `${modelName} #${uuid}` : "Page"
    return <NotFound text={`${text} not found.`} />
  }
  if (error.status === 500) {
    return (
      <NotFound text="There was an error processing this request. Please contact an administrator." />
    )
  }
  return `${error.message}`
}

export const toggleLoading = (loading, showLoading, hideLoading) => {
  if (loading) {
    if (typeof showLoading === "function") {
      showLoading()
    }
  } else {
    if (typeof hideLoading === "function") {
      hideLoading()
    }
  }
}

export const applyPageProps = (setPageProps, pageProps) => {
  const pp = _isEmpty(pageProps) ? DEFAULT_PAGE_PROPS : pageProps
  if (typeof setPageProps === "function") {
    setPageProps(Object.assign({}, pp))
  }
}

export const applySearchProps = (setSearchProps, searchProps) => {
  const sp = _isEmpty(searchProps) ? DEFAULT_SEARCH_PROPS : searchProps
  if (typeof setSearchProps === "function") {
    setSearchProps(Object.assign({}, sp))
  }
}

export const getSearchQuery = searchQuery => {
  let query = {}
  if (!_isEmpty(searchQuery.text)) {
    query.text = searchQuery.text
  }
  if (searchQuery.filters) {
    searchQuery.filters.forEach(filter => {
      if (filter.value) {
        if (filter.value.toQuery) {
          const toQuery =
            typeof filter.value.toQuery === "function"
              ? filter.value.toQuery()
              : filter.value.toQuery
          Object.assign(query, toQuery)
        } else {
          query[filter.key] = filter.value
        }
      }
    })
  }
  return query
}

@@ -2032,16 +2032,24 @@
    () =%3E
+ %7B%0A     
  toggleL
@@ -2107,16 +2107,198 @@
 Loading)
+%0A      return function cleanup() %7B%0A        // Make sure loading indicator is hidden when 'unmounting'%0A        toggleLoading(false, props.showLoading, props.hideLoading)%0A      %7D%0A    %7D
 ,%0A    %5Bp

Make sure the loading indicator is hidden when 'unmounting'