import { createAction } from 'redux-act'

import { remoteFunction } from '../../util/webextensionRPC'
import analytics from '../../analytics'
import { Thunk } from '../../options/types'
import * as selectors from './selectors'
import * as constants from './constants'
import { SearchResult } from '../types'
import { selectors as searchBar, acts as searchBarActs } from '../search-bar'
import { selectors as filters } from '../../search-filters'
import { handleDBQuotaErrors } from 'src/util/error-handler'
import {
    auth,
    bookmarks,
    collections,
    notifications,
    contentSharing,
} from 'src/util/remote-functions-background'
import * as modalActions from 'src/overview/modals/actions'

const createSocialBookmarkRPC = remoteFunction('addSocialBookmark')
const deleteSocialBookmarkRPC = remoteFunction('delSocialBookmark')

export const setBetaFeatures = createAction<boolean>('beta/setBeta')
export const setOptInFeatures = createAction<boolean>('feature/set')

export const addTag = createAction('results/localAddTag', (tag, index) => ({
    tag,
    index,
}))

export const delTag = createAction('results/localDelTag', (tag, index) => ({
    tag,
    index,
}))

export const addList = createAction('results/localAddList', (list, index) => ({
    list,
    index,
}))

export const delList = createAction('results/localDelList', (list, index) => ({
    list,
    index,
}))

export const setShowOnboardingMessage = createAction<boolean>(
    'results/setShowOnboardingMessage',
)

export const hideResultItem = createAction<string>('results/hideResultItem')
export const changeHasBookmark = createAction<number>(
    'results/changeHasBookmark',
)
export const resetSearchResult = createAction('results/resetSearchResult')
export const setSearchResult = createAction<SearchResult>(
    'results/setSearchResult',
)
export const appendSearchResult = createAction<SearchResult>(
    'results/appendSearchResult',
)
export const setLoading = createAction<boolean>('results/setLoading')
export const setAreAnnotationsExpanded = createAction<boolean>(
    'results/setAreAnnotationsExpanded',
)
export const toggleAreAnnotationsExpanded = createAction(
    'results/toggleAreAnnotationsExpanded',
)
export const resetActiveListIndex = createAction('results/resetActiveListIndex')
export const setActiveListIndex = createAction<number>(
    'results/setActiveListIndex',
)
export const resetActiveTagIndex = createAction('results/resetActiveTagIndex')
export const setActiveTagIndex = createAction<number>(
    'results/setActiveTagIndex',
)
export const resetActiveSidebarIndex = createAction(
    'results/resetActiveSidebarIndex',
)
export const setActiveSidebarIndex = createAction<number>(
    'results/setActiveSidebarIndex',
)
export const resetActiveCopyPasterIndex = createAction(
    'results/resetActiveCopyPasterIndex',
)
export const setActiveCopyPasterIndex = createAction<number>(
    'results/setActiveCopyPasterIndex',
)
export const nextPage = createAction('results/nextPage')
export const resetPage = createAction('results/resetPage')
export const setSearchType = createAction<'page' | 'notes' | 'social'>(
    'results/setSearchType',
)
export const initSearchCount = createAction('overview/initSearchCount')
export const incSearchCount = createAction('overview/incSearchCount')

export const updateListName = createAction<[string, string]>(
    'overview/updateListName',
)

export const toggleResultCopyPaster = createAction(
    'overview/toggleResultCopyPaster',
)
export const setResultCopyPasterShown = createAction<boolean>(
    'overview/setResultCopyPasterShown',
)

export const clickShareList: () => Thunk = () => async (dispatch, getState) => {
    const listId = filters.listIdFilter(getState())
    const list = await collections.fetchListById({ id: +listId })

    dispatch(
        modalActions.show({
            modalId: 'ShareListModal',
            options: {
                list,
                auth,
                contentSharing,
                isPioneer: true,
                isShown: true,
            },
        }),
    )
}

export const toggleBookmark: (args: {
    url: string
    fullUrl: string
    index: number
}) => Thunk = ({ url, fullUrl, index }) => async (dispatch, getState) => {
    const results = selectors.results(getState())
    const { hasBookmark, user } = results[index]
    dispatch(changeHasBookmark(index))

    let bookmarkRPC: (args: { url: string; fullUrl: string }) => Promise<void>
    // tslint:disable-next-line: prefer-conditional-expression
    if (hasBookmark) {
        bookmarkRPC = user ? deleteSocialBookmarkRPC : bookmarks.delPageBookmark
    } else {
        bookmarkRPC = user ? createSocialBookmarkRPC : bookmarks.addPageBookmark
    }

    try {
        await bookmarkRPC({ url, fullUrl })
    } catch (err) {
        dispatch(changeHasBookmark(index))
        handleDBQuotaErrors(
            (error) =>
                notifications.create({
                    requireInteraction: false,
                    title: 'Memex error: starring page',
                    message: error.message,
                }),
            () => remoteFunction('dispatchNotification')('db_error'),
        )(err)
    }
}

export const updateSearchResult: (a: any) => Thunk = ({
    searchResult,
    overwrite = false,
}) => (dispatch, getState) => {
    trackSearch(searchResult, overwrite, getState())

    const searchAction = overwrite ? setSearchResult : appendSearchResult

    dispatch(searchAction(searchResult))
    dispatch(setLoading(false))
}

// Egg
export const easter: () => Thunk = () => (dispatch) =>
    dispatch(
        updateSearchResult({
            overwrite: true,
            searchResult: {
                resultsExhausted: true,
                totalCount: 1,
                docs: [
                    {
                        content: { title: constants.EGG_TITLE },
                        url: constants.EGG_URL,
                        screenshot: constants.EGG_IMG,
                        displayTime: Date.now().toString(),
                        hasBookmark: false,
                        tags: [],
                        lists: [],
                    },
                ],
            },
        }),
    )

export const toggleShowTagsPicker: (i: number) => Thunk = (index) => (
    dispatch,
    getState,
) => {
    const activeTagIndex = selectors.activeTagIndex(getState())

    if (activeTagIndex === index) {
        dispatch(resetActiveTagIndex())
    } else {
        dispatch(resetActiveListIndex())
        dispatch(resetActiveCopyPasterIndex())
        dispatch(setActiveTagIndex(index))
    }
}

export const toggleShowListsPicker: (i: number) => Thunk = (index) => (
    dispatch,
    getState,
) => {
    const activeListIndex = selectors.activeListIndex(getState())

    if (activeListIndex === index) {
        dispatch(resetActiveListIndex())
    } else {
        dispatch(resetActiveTagIndex())
        dispatch(resetActiveCopyPasterIndex())

        dispatch(setActiveListIndex(index))
    }
}

export const toggleShowCopyPaster: (i: number) => Thunk = (index) => (
    dispatch,
    getState,
) => {
    const activeCopyPasterIndex = selectors.activeCopyPasterIndex(getState())

    if (activeCopyPasterIndex === index) {
        dispatch(resetActiveCopyPasterIndex())
    } else {
        dispatch(resetActiveTagIndex())
        dispatch(resetActiveListIndex())

        dispatch(setActiveCopyPasterIndex(index))
    }
}

/**
 * Increments the page state before scheduling another search.
 */
export const getMoreResults: (fromOverview?: boolean) => Thunk = (
    fromOverview = true,
) => (dispatch) => {
    dispatch(nextPage())
    dispatch(searchBarActs.search({ fromOverview }))
}

// Analytics use
function trackSearch(searchResult, overwrite, state) {
    if (searchBar.isEmptyQuery(state)) {
        return
    }

    // Value should be set as # results (if non-default search)
    const value = overwrite ? searchResult.totalCount : undefined

    const action =
        searchResult.docs.length > 0
            ? overwrite
                ? 'successViaOverview'
                : 'paginateSearch'
            : 'failViaOverview'

    const name = overwrite
        ? searchBar.queryParamsDisplay(state)
        : selectors.currentPageDisplay(state)

    analytics.trackEvent({ category: 'Search', action, name, value })
}
