import marked from 'marked';
import MapSearchIcon from 'mdi-react/MapSearchIcon';
import * as React from 'react';
import { Link } from 'react-router-dom';
import { combineLatest, of, Subject, Subscription } from 'rxjs';
import { catchError, concat, map, switchMap } from 'rxjs/operators';
import { currentUser } from '../../auth';
import { Form } from '../../components/Form';
import { HeroPage } from '../../components/HeroPage';
import { PageTitle } from '../../components/PageTitle';
import { RepoLink } from '../../repo/RepoLink';
import { currentConfiguration } from '../../settings/configuration';
import { eventLogger } from '../../tracking/eventLogger';
import { RepositoryIcon } from '../../util/icons'; // TODO: Switch to mdi icon
import { fetchReposByQuery } from '../backend';
import { submitSearch } from '../helpers';
import { queryUpdates } from './QueryInput';
import { QueryInput } from './QueryInput';
import { SearchButton } from './SearchButton';
const ScopeNotFound = () => (React.createElement(HeroPage, { icon: MapSearchIcon, title: "404: Not Found", subtitle: React.createElement(React.Fragment, null,
        "No search page found with this scope ID. Add an ID and description to a search scope to create a search page. See",
        ' ',
        React.createElement("a", { href: "https://about.sourcegraph.com/docs/server/config/search-scopes" }, "search scope documentation"),
        ".") }));
export class ScopePage extends React.Component {
    constructor() {
        super(...arguments);
        this.subscriptions = new Subscription();
        this.propUpdates = new Subject();
        this.showMoreClicks = new Subject();
        this.state = {
            query: '',
            repositories: [],
            value: '',
            first: 50,
        };
        this.onQueryChange = (query) => this.setState({ query });
        this.onSubmit = (event) => {
            event.preventDefault();
            submitSearch(this.props.history, { query: `${this.state.value} ${this.state.query}` }, 'home');
        };
        this.onShowMore = (event) => {
            this.showMoreClicks.next();
        };
    }
    componentDidMount() {
        eventLogger.logViewEvent('Scope');
        this.subscriptions.add(currentUser.subscribe(user => this.setState({ user })));
        this.subscriptions.add(combineLatest(this.propUpdates, currentConfiguration.pipe(map((config) => config['search.scopes'] || [])))
            .pipe(switchMap(([props, searchScopes]) => {
            this.setState({ searchScopes });
            const matchedScope = searchScopes.find(o => o.id === props.match.params.id);
            if (matchedScope) {
                const markdownDescription = marked(matchedScope.description || '', {
                    gfm: true,
                    breaks: true,
                    sanitize: true,
                });
                queryUpdates.next(matchedScope.value);
                if (matchedScope.value.includes('repo:') || matchedScope.value.includes('repogroup:')) {
                    return of(Object.assign({}, matchedScope, { markdownDescription })).pipe(concat(fetchReposByQuery(matchedScope.value).pipe(map(repositories => ({ repositories, errorMessage: undefined })), catchError(err => {
                        console.error(err);
                        return [{ errorMessage: err.message, repositories: [], first: 0 }];
                    }))));
                }
                queryUpdates.next(matchedScope.value);
                return [
                    Object.assign({}, matchedScope, { markdownDescription, repositories: [], errorMessage: undefined, first: 0 }),
                ];
            }
            return [
                {
                    id: undefined,
                    name: undefined,
                    value: '',
                    markdownDescription: '',
                    repositories: [],
                    errorMessage: undefined,
                    first: 0,
                },
            ];
        }))
            .subscribe(state => this.setState(state)));
        this.subscriptions.add(this.showMoreClicks.subscribe(() => this.setState(state => ({ first: state.first + 50 }))));
        this.propUpdates.next(this.props);
    }
    componentWillReceiveProps(newProps) {
        this.propUpdates.next(newProps);
    }
    componentWillUnmount() {
        this.subscriptions.unsubscribe();
    }
    render() {
        if (!this.state.searchScopes) {
            return null;
        }
        if (!this.state.searchScopes.some((element) => element.id === this.props.match.params.id)) {
            return React.createElement(ScopeNotFound, null);
        }
        return (React.createElement("div", { className: "scope-page" },
            React.createElement("div", { className: "scope-page__container" },
                React.createElement("header", null,
                    React.createElement("h1", { className: "scope-page__title" }, this.state.name),
                    this.state.markdownDescription && (React.createElement("div", { className: "scope-page__section", dangerouslySetInnerHTML: { __html: this.state.markdownDescription || '' } }))),
                React.createElement("section", null,
                    React.createElement(Form, { className: "scope-page__section-search", onSubmit: this.onSubmit },
                        React.createElement("div", { className: "scope-page__input-scope", title: this.state.value },
                            React.createElement("span", { className: "scope-page__input-scope-text" }, this.state.value)),
                        React.createElement(QueryInput, { value: this.state.query, onChange: this.onQueryChange, prependQueryForSuggestions: this.state.value, autoFocus: true, location: this.props.location, history: this.props.history, placeholder: "Search in this scope..." }),
                        React.createElement(SearchButton, null))),
                React.createElement(PageTitle, { title: this.state.name }),
                React.createElement("section", { className: "scope-page__repos" },
                    React.createElement("div", null,
                        React.createElement("div", null,
                            this.state.errorMessage && (React.createElement("p", { className: "alert alert-danger" }, this.state.errorMessage)),
                            !this.state.errorMessage &&
                                (this.state.repositories && this.state.repositories.length > 0 ? (React.createElement("div", null,
                                    React.createElement("p", null, "Repositories included in this scope:"),
                                    React.createElement("div", null, this.state.repositories.slice(0, this.state.first).map((repo, i) => (React.createElement("div", { key: i, className: "scope-page__row" },
                                        React.createElement(Link, { to: repo.url, className: "scope-page__link" },
                                            React.createElement(RepositoryIcon, { className: "icon-inline scope-page__link-icon" }),
                                            React.createElement(RepoLink, { repoPath: repo.name, to: null })))))),
                                    React.createElement("p", { className: "scope-page__count" },
                                        this.state.repositories.length,
                                        ' ',
                                        this.state.repositories.length > 1 ? 'repositories ' : 'repository ',
                                        ' ',
                                        "total",
                                        ' ',
                                        this.state.repositories.length > this.state.first
                                            ? `(showing first ${this.state.first})`
                                            : '',
                                        ' '),
                                    this.state.first < this.state.repositories.length && (React.createElement("button", { className: "btn btn-secondary btn-sm scope-page__show-more", onClick: this.onShowMore }, "Show more")))) : (React.createElement("p", null, "All repositories included in this scope")))),
                        window.context.sourcegraphDotComMode &&
                            !this.state.user && (React.createElement("small", null,
                            "Have an idea for a search scope for your community, or want to add a repository to this scope? Tweet us ",
                            React.createElement("a", { href: "https://twitter.com/srcgraph" }, "@srcgraph"),
                            ".")))))));
    }
}
//# sourceMappingURL=ScopePage.js.map