import { escapeRegExp } from 'lodash';
import * as path from 'path';
import * as React from 'react';
import { matchPath } from 'react-router';
import { NavLink } from 'react-router-dom';
import { Subject, Subscription } from 'rxjs';
import { catchError, distinctUntilChanged, filter, map, mergeMap } from 'rxjs/operators';
import { authRequired } from '../../auth';
import { currentUser } from '../../auth';
import { Tooltip } from '../../components/tooltip/Tooltip';
import { routes } from '../../routes';
import { currentConfiguration } from '../../settings/configuration';
import { eventLogger } from '../../tracking/eventLogger';
import { fetchSearchScopes } from '../backend';
import { FilterChip } from '../FilterChip';
import { submitSearch, toggleSearchFilter } from '../helpers';
export class SearchFilterChips extends React.PureComponent {
    constructor(props) {
        super(props);
        this.componentUpdates = new Subject();
        this.subscriptions = new Subscription();
        this.onSearchScopeClicked = (value) => {
            eventLogger.log('SearchScopeClicked', {
                search_filter: {
                    value,
                },
            });
            submitSearch(this.props.history, { query: toggleSearchFilter(this.props.query, value) }, 'filter');
        };
        this.state = { user: null };
        this.subscriptions.add(authRequired
            .pipe(filter(authRequired => !authRequired), mergeMap(() => fetchSearchScopes()), catchError(err => {
            console.error(err);
            return [];
        }), map((remoteScopes) => ({ remoteScopes })))
            .subscribe(newState => this.setState(newState), err => console.error(err)));
    }
    componentDidMount() {
        this.subscriptions.add(currentConfiguration.pipe(map(config => config['search.scopes'] || [])).subscribe(searchScopes => this.setState({
            configuredScopes: searchScopes,
        })));
        this.subscriptions.add(currentUser.subscribe(user => this.setState({ user })));
        // Update tooltip text immediately after clicking.
        this.subscriptions.add(this.componentUpdates
            .pipe(distinctUntilChanged((a, b) => a.query === b.query))
            .subscribe(() => Tooltip.forceUpdate()));
    }
    componentWillReceiveProps(newProps) {
        this.componentUpdates.next(newProps);
    }
    componentWillUnmount() {
        this.subscriptions.unsubscribe();
    }
    render() {
        const scopes = this.getScopes();
        return (React.createElement("div", { className: "search-filter-chips" },
            scopes
                .filter(scope => scope.value !== '')
                .map((scope, i) => (React.createElement(FilterChip, { query: this.props.query, onFilterChosen: this.onSearchScopeClicked, key: i, value: scope.value, name: scope.name }))),
            this.state.user && (React.createElement("div", { className: "search-filter-chips__edit" },
                React.createElement(NavLink, { className: "search-filter-chips__add-edit", to: "/settings", "data-tooltip": scopes.length > 0 ? 'Edit search scopes' : undefined },
                    React.createElement("small", { className: "search-filter-chips__center" }, scopes.length === 0 ? (React.createElement("span", { className: "search-filter-chips__add-scopes" }, "Add search scopes for quick filtering")) : (`Edit`)))))));
    }
    getScopes() {
        const allScopes = [];
        if (this.state.configuredScopes) {
            allScopes.push(...this.state.configuredScopes);
        }
        if (this.state.remoteScopes) {
            allScopes.push(...this.state.remoteScopes);
        }
        allScopes.push(...this.getScopesForCurrentRoute());
        return allScopes;
    }
    /**
     * Returns contextual scopes for the current route (such as "This Repository" and
     * "This Directory").
     */
    getScopesForCurrentRoute() {
        const scopes = [];
        // This is basically a programmatical <Switch> with <Route>s
        // see https://reacttraining.com/react-router/web/api/matchPath
        // and https://reacttraining.com/react-router/web/example/sidebar
        for (const route of routes) {
            const match = matchPath(this.props.location.pathname, {
                path: route.path,
                exact: route.exact,
            });
            if (match) {
                switch (match.path) {
                    case '/:repoRev+': {
                        // Repo page
                        const [repoPath] = match.params.repoRev.split('@');
                        scopes.push(scopeForRepo(repoPath));
                        break;
                    }
                    case '/:repoRev+/-/tree/:filePath+':
                    case '/:repoRev+/-/blob/:filePath+': {
                        // Blob/tree page
                        const isTree = match.path === '/:repoRev+/-/tree/:filePath+';
                        const [repoPath] = match.params.repoRev.split('@');
                        scopes.push({
                            value: `repo:^${escapeRegExp(repoPath)}$`,
                        });
                        if (match.params.filePath) {
                            const dirname = isTree ? match.params.filePath : path.dirname(match.params.filePath);
                            if (dirname !== '.') {
                                scopes.push({
                                    value: `repo:^${escapeRegExp(repoPath)}$ file:^${escapeRegExp(dirname)}/`,
                                });
                            }
                        }
                        break;
                    }
                }
                break;
            }
        }
        return scopes;
    }
}
function scopeForRepo(repoPath) {
    return {
        value: `repo:^${escapeRegExp(repoPath)}$`,
    };
}
//# sourceMappingURL=SearchFilterChips.js.map