import { LoadingSpinner } from '@sourcegraph/react-loading-spinner';
import CheckCircleIcon from 'mdi-react/CheckCircleIcon';
import prettyBytes from 'pretty-bytes';
import * as React from 'react';
import { Link } from 'react-router-dom';
import { Subject, Subscription } from 'rxjs';
import { map, switchMap, tap } from 'rxjs/operators';
import { gql, queryGraphQL } from '../../backend/graphql';
import { PageTitle } from '../../components/PageTitle';
import { Timestamp } from '../../components/time/Timestamp';
import { eventLogger } from '../../tracking/eventLogger';
import { createAggregateError } from '../../util/errors';
import { pluralize } from '../../util/strings';
/**
 * Fetches a repository's text search index information.
 */
function fetchRepositoryTextSearchIndex(id) {
    return queryGraphQL(gql `
            query RepositoryTextSearchIndex($id: ID!) {
                node(id: $id) {
                    ... on Repository {
                        textSearchIndex {
                            status {
                                updatedAt
                                contentByteSize
                                contentFilesCount
                                indexByteSize
                                indexShardsCount
                            }
                            refs {
                                ref {
                                    displayName
                                    url
                                }
                                indexed
                                current
                                indexedCommit {
                                    oid
                                    abbreviatedOID
                                    commit {
                                        url
                                    }
                                }
                            }
                        }
                    }
                }
            }
        `, { id }).pipe(map(({ data, errors }) => {
        if (!data || !data.node || errors) {
            throw createAggregateError(errors);
        }
        return data.node.textSearchIndex;
    }));
}
const TextSearchIndexedRef = ({ repo, indexedRef, }) => {
    let Icon;
    let iconClassName;
    if (indexedRef.indexed && indexedRef.current) {
        Icon = CheckCircleIcon;
        iconClassName = 'current';
    }
    else {
        Icon = LoadingSpinner;
        iconClassName = 'stale';
    }
    return (React.createElement("li", { className: "repo-settings-index-page__ref" },
        React.createElement(Icon, { className: `icon-inline repo-settings-index-page__ref-icon repo-settings-index-page__ref-icon--${iconClassName}` }),
        React.createElement(Link, { to: indexedRef.ref.url },
            React.createElement("strong", null,
                React.createElement("code", null, indexedRef.ref.displayName))),
        ' ',
        indexedRef.indexed ? (React.createElement("span", null,
            "\u00A0\u2014 indexed at",
            ' ',
            React.createElement("code", null,
                React.createElement(Link, { to: indexedRef.indexedCommit && indexedRef.indexedCommit.commit
                        ? indexedRef.indexedCommit.commit.url
                        : repo.url }, indexedRef.indexedCommit.abbreviatedOID)),
            ' ',
            indexedRef.current ? '(up to date)' : '(index update in progress)')) : (React.createElement("span", null, "\u00A0\u2014 initial indexing in progress"))));
};
/**
 * The repository settings index page.
 */
export class RepoSettingsIndexPage extends React.PureComponent {
    constructor() {
        super(...arguments);
        this.state = { loading: true };
        this.updates = new Subject();
        this.subscriptions = new Subscription();
    }
    componentDidMount() {
        eventLogger.logViewEvent('RepoSettingsIndex');
        this.subscriptions.add(this.updates
            .pipe(tap(() => this.setState({ loading: true })), switchMap(() => fetchRepositoryTextSearchIndex(this.props.repo.id)))
            .subscribe(textSearchIndex => this.setState({ textSearchIndex, loading: false }), error => this.setState({ error, loading: false })));
        this.updates.next();
    }
    componentWillUnmount() {
        this.subscriptions.unsubscribe();
    }
    render() {
        return (React.createElement("div", { className: "repo-settings-index-page" },
            React.createElement(PageTitle, { title: "Index settings" }),
            React.createElement("h2", null, "Indexing"),
            this.state.loading && React.createElement(LoadingSpinner, { className: "icon-inline" }),
            this.state.error && (React.createElement("div", { className: "alert alert-danger" },
                "Error getting repository index status:",
                React.createElement("br", null),
                React.createElement("code", null, this.state.error.message))),
            !this.state.error &&
                !this.state.loading &&
                (this.state.textSearchIndex ? (React.createElement(React.Fragment, null,
                    React.createElement("p", null, "Index branches to enhance search performance at scale."),
                    this.state.textSearchIndex.refs && (React.createElement("ul", { className: "repo-settings-index-page__refs" }, this.state.textSearchIndex.refs.map((ref, i) => (React.createElement(TextSearchIndexedRef, { key: i, repo: this.props.repo, indexedRef: ref }))))),
                    this.state.textSearchIndex.status && (React.createElement(React.Fragment, null,
                        React.createElement("h3", null, "Statistics"),
                        React.createElement("table", { className: "table repo-settings-index-page__stats" },
                            React.createElement("tbody", null,
                                React.createElement("tr", null,
                                    React.createElement("th", null, "Last updated"),
                                    React.createElement("td", null,
                                        React.createElement(Timestamp, { date: this.state.textSearchIndex.status.updatedAt }))),
                                React.createElement("tr", null,
                                    React.createElement("th", null, "Content size"),
                                    React.createElement("td", null,
                                        prettyBytes(this.state.textSearchIndex.status.contentByteSize),
                                        " (",
                                        this.state.textSearchIndex.status.contentFilesCount,
                                        ' ',
                                        pluralize('file', this.state.textSearchIndex.status.contentFilesCount),
                                        ")")),
                                React.createElement("tr", null,
                                    React.createElement("th", null, "Index size"),
                                    React.createElement("td", null,
                                        prettyBytes(this.state.textSearchIndex.status.indexByteSize),
                                        " (",
                                        this.state.textSearchIndex.status.indexShardsCount,
                                        ' ',
                                        pluralize('shard', this.state.textSearchIndex.status.indexShardsCount),
                                        ")")))))))) : (React.createElement("div", { className: "alert alert-info" },
                    "This Sourcegraph site doesn't support indexed search. See",
                    ' ',
                    React.createElement("a", { href: "https://github.com/sourcegraph/sourcegraph/pull/239" }, "PR #239"),
                    " for information on how to enable it.")))));
    }
}
//# sourceMappingURL=RepoSettingsIndexPage.js.map