import React from 'react'
import PropTypes from 'prop-types'
import modalTypes from 'containers/modal-manager/modal-types'
import Button from 'react-uikit/button'
import Layout from 'components/layout'
import TradeFilterDialog from 'components/trade-filter-dialog'
import TradeFilters from 'components/trade-filters'
import TradeHeader from 'components/trade-header'
import TradeTable from 'components/trade-table'

import securityTypes from 'common-fe/constants/security-types'
import {ETF} from 'global/models'
import securityFilters from 'global/constants/security-filters'

import AppliedFilters from './partials/trade-etfs-applied-filters'
import TradeETFsTableRowPlaceholder from './partials/trade-etfs-table-row-placeholder'
import TradeETFsTableRow from './partials/trade-etfs-table-row'
import TradeETFsTableStatus from './partials/trade-etfs-table-status'

import {allowedFilters, filters} from './constants'
import content from './content'
import BEMModule from 'utils/bem'
import styles from './styles.scss'
const bem = new BEMModule(styles)

class TradeETFsPage extends React.Component {
    static pageTitle = content.ETF.title
    static filters = filters

    allowedFilters = allowedFilters

    allowedFilterParams = this.allowedFilters
        .map((key) => TradeETFsPage.filters[key].inputs)
        .flatten()

    state = {appliedFilters: {}}

    get results() {
        return this.isFiltersApplied
            ? this.props.search.results
            : {
                  total: 0,
                  pages: 1,
                  list: [{value: '', label: 'No filters applied'}],
              }
    }

    get isFiltersApplied() {
        const appliedSearchParams = Object.keys(this.state.appliedFilters)
        return this.allowedFilterParams.some((param) =>
            appliedSearchParams.includes(param)
        )
    }

    get data() {
        return this.results.list
    }

    get tableHead() {
        const {sortOrder, sortBy} = this.state.appliedFilters

        const tableHead = {
            performance: {
                label: 'Performance',
                value: ETF.performance,
            },
            statistics: {
                label: 'Statistics',
                value: ETF.statistics,
            },
            currentPrice: {
                isSortable: true,
                label: 'Price',
                value: ETF.currentPrice,
            },
        }

        if (sortBy) {
            tableHead[sortBy].sort = sortOrder
        }

        return [
            tableHead.performance,
            tableHead.statistics,
            tableHead.currentPrice,
        ]
    }

    get headProps() {
        const {total = 0} = this.results
        const className = bem.classNames('c-trade-etfs-page__thead')

        return {
            content,
            className,
            totalNumber: total,
            onSort: ({value: sortBy, sort = 'DESC'}) => {
                const sortOrder = sort === 'ASC' ? 'DESC' : 'ASC'
                this.applyFilter({
                    filterKey: 'sort',
                    filter: {sortBy, sortOrder},
                })
            },
        }
    }

    get rowProps() {
        return {
            onTrade: ({securityId}) => {
                this.props.showModal &&
                    this.props.showModal({
                        securityId,
                        shouldSubscribe: true,
                        type: modalTypes.MODAL_ORDER,
                    })
            },
        }
    }

    get rowTemplate() {
        const {
            search: {isEmpty, isError, isLoading},
        } = this.props

        if (!this.isFiltersApplied) {
            return TradeETFsTableRowPlaceholder
        }

        if (isError || isLoading || isEmpty) {
            return TradeETFsTableStatus
        }

        return TradeETFsTableRow
    }

    componentDidMount() {
        const {input} = this.props.search

        const appliedFilters = Object.entries(input).reduce(
            (filters, [filterParam, value]) => {
                if (!this.allowedFilterParams.includes(filterParam)) {
                    return filters
                }
                filters[filterParam] = value
                return filters
            },
            {}
        )

        this.setState({
            appliedFilters: {
                ...appliedFilters,
                sortBy: ETF.currentPrice,
                sortOrder: 'ASC',
            },
        })
    }

    applyFilter = ({filterKey, filter: filterParams}) => {
        const {getSearchResults} = this.props

        const appliedFilters = {...this.state.appliedFilters}
        const filter = TradeETFsPage.filters[filterKey]

        filter &&
            filter.inputs &&
            filter.inputs.forEach((filterParam) => {
                delete appliedFilters[filterParam]
            })

        getSearchResults &&
            getSearchResults(
                {
                    ...appliedFilters,
                    ...filterParams,
                    page: 1,
                },
                {overrideLoader: true}
            )

        this.setState({appliedFilters: {...appliedFilters, ...filterParams}})
    }

    removeFilter = (filterKey) => {
        const {
            search: {input},
        } = this.props

        const appliedFilters = {...this.state.appliedFilters}
        const additionalParams = {...input}

        const filter = TradeETFsPage.filters[filterKey]

        filter.inputs &&
            filter.inputs.forEach((filterParam) => {
                delete appliedFilters[filterParam]
                delete additionalParams[filterParam]
            })

        if (Object.keys(appliedFilters).length) {
            this.props.getSearchResults &&
                this.props.getSearchResults(
                    {...appliedFilters, page: 1},
                    {overrideLoader: true}
                )
        }

        this.setState({appliedFilters})
    }

    setPage = (page) => {
        const {
            search: {input},
            getSearchResults,
        } = this.props

        getSearchResults &&
            getSearchResults(
                {...input, ...this.state.appliedFilters, page},
                {overrideLoader: true}
            )
    }

    togglePopular = () => {
        const isPopular = !this.state.appliedFilters.popular

        if (isPopular) {
            this.applyFilter({
                filterKey: [securityFilters.POPULAR],
                filter: {popular: isPopular},
            })
        } else {
            this.removeFilter(securityFilters.POPULAR)
        }
    }

    render() {
        const {
            search: {
                input: {page = 1},
            },
        } = this.props

        const {pages = 1} = this.results
        // In the event that we are removing all our filters, we want to display
        // the "getting started" steps which requires us to be in a default state.
        // In this case, we will set our current page to 1.
        const currentPage = page > pages ? 1 : page

        const rootClassNames = bem.classNames('c-trade-etfs-page')
        const dividerClassNames = bem.classNames('c-trade-etfs-page__divider')
        const appliedFilters = this.state.appliedFilters

        return (
            <React.Fragment>
                <Layout.Section hasBackground className={rootClassNames}>
                    <TradeHeader
                        description={content.ETF.description}
                        title={content.ETF.title}
                        link={content.ETF.learnMoreUrl}
                    />
                    <TradeFilters>
                        {this.allowedFilters.map((filter) => {
                            const {
                                value,
                                inputs,
                                ...props
                            } = TradeETFsPage.filters[filter]

                            if (value === securityFilters.POPULAR) {
                                return (
                                    <div
                                        key={value}
                                        className={dividerClassNames}
                                    >
                                        <hr />
                                        <Button
                                            isOutline={!appliedFilters.popular}
                                            variant="primary"
                                            size="small"
                                            onClick={this.togglePopular}
                                        >
                                            {props.label}
                                        </Button>
                                    </div>
                                )
                            }

                            const appliedFilter = inputs.reduce(
                                (result, filterParam) => {
                                    const value = appliedFilters[filterParam]

                                    if (value) {
                                        result[filterParam] = value
                                    }

                                    return result
                                },
                                {}
                            )

                            return (
                                <TradeFilterDialog
                                    {...props}
                                    appliedFilter={appliedFilter}
                                    filterKey={value}
                                    key={value}
                                    securityType={securityTypes.FUND.value}
                                    onApplyFilter={this.applyFilter}
                                />
                            )
                        })}
                    </TradeFilters>
                </Layout.Section>

                <AppliedFilters
                    appliedFilters={appliedFilters}
                    removeFilter={this.removeFilter}
                />

                <Layout.Section hasBackground className={rootClassNames}>
                    <TradeTable
                        currentPage={currentPage}
                        data={this.data}
                        headProps={this.headProps}
                        linkToInfo={content.ETF.howToRead}
                        pageCount={pages}
                        renderRow={this.rowTemplate}
                        rowProps={this.rowProps}
                        tableHead={this.tableHead}
                        onPageChange={this.setPage}
                    />
                </Layout.Section>
            </React.Fragment>
        )
    }
}

TradeETFsPage.propTypes = {
    getSearchResults: PropTypes.func,
    page: PropTypes.number,
    search: PropTypes.shape({
        input: PropTypes.object,
        isEmpty: PropTypes.bool,
        isError: PropTypes.bool,
        isLoading: PropTypes.bool,
        results: PropTypes.shape({
            list: PropTypes.array,
            pages: PropTypes.number,
            total: PropTypes.number,
        }),
    }),
    securityType: PropTypes.string,
    showModal: PropTypes.func,
}

export default TradeETFsPage
