import { LoadingSpinner } from '@sourcegraph/react-loading-spinner';
import { upperFirst } from 'lodash';
import * as React from 'react';
import { merge, of, Subject, Subscription } from 'rxjs';
import { catchError, distinctUntilChanged, map, switchMap } from 'rxjs/operators';
import { gql, queryGraphQL } from '../../backend/graphql';
import { PageTitle } from '../../components/PageTitle';
import { eventLogger } from '../../tracking/eventLogger';
import { createAggregateError, isErrorLike } from '../../util/errors';
import { RepositoryCompareCommitsPage } from './RepositoryCompareCommitsPage';
import { RepositoryCompareDiffPage } from './RepositoryCompareDiffPage';
function queryRepositoryComparison(args) {
    return queryGraphQL(gql `
            query RepositoryComparison($repo: ID!, $base: String, $head: String) {
                node(id: $repo) {
                    ... on Repository {
                        comparison(base: $base, head: $head) {
                            range {
                                expr
                                baseRevSpec {
                                    object {
                                        oid
                                    }
                                }
                                headRevSpec {
                                    object {
                                        oid
                                    }
                                }
                            }
                        }
                    }
                }
            }
        `, args).pipe(map(({ data, errors }) => {
        if (!data || !data.node) {
            throw createAggregateError(errors);
        }
        const repo = data.node;
        if (!repo.comparison ||
            !repo.comparison.range ||
            !repo.comparison.range.baseRevSpec ||
            !repo.comparison.range.baseRevSpec.object ||
            !repo.comparison.range.headRevSpec ||
            !repo.comparison.range.headRevSpec.object ||
            errors) {
            throw createAggregateError(errors);
        }
        eventLogger.log('RepositoryComparisonFetched');
        return repo.comparison.range;
    }));
}
/** A page with an overview of the comparison. */
export class RepositoryCompareOverviewPage extends React.PureComponent {
    constructor() {
        super(...arguments);
        this.state = {};
        this.componentUpdates = new Subject();
        this.subscriptions = new Subscription();
    }
    componentDidMount() {
        eventLogger.logViewEvent('RepositoryCompareOverview');
        this.subscriptions.add(this.componentUpdates
            .pipe(distinctUntilChanged((a, b) => a.repo.id === b.repo.id && a.base.rev === b.base.rev && a.head.rev === b.head.rev), switchMap(({ repo, base, head }) => {
            if (!base.rev && !head.rev) {
                return of({ rangeOrError: null });
            }
            return merge(of({ rangeOrError: undefined }), queryRepositoryComparison({
                repo: repo.id,
                base: base.rev || null,
                head: head.rev || null,
            }).pipe(catchError(error => [error]), map(c => ({ rangeOrError: c }))));
        }))
            .subscribe(stateUpdate => this.setState(stateUpdate), error => console.error(error)));
        this.componentUpdates.next(this.props);
    }
    componentWillReceiveProps(nextProps) {
        this.componentUpdates.next(nextProps);
    }
    componentWillUnmount() {
        this.subscriptions.unsubscribe();
    }
    render() {
        return (React.createElement("div", { className: "repository-compare-page" },
            React.createElement(PageTitle, { title: "Compare" }),
            this.state.rangeOrError === null ? (React.createElement("p", null, "Enter two Git revspecs to compare.")) : this.state.rangeOrError === undefined ? (React.createElement(LoadingSpinner, { className: "icon-inline" })) : isErrorLike(this.state.rangeOrError) ? (React.createElement("div", { className: "alert alert-danger mt-2" },
                "Error: ",
                upperFirst(this.state.rangeOrError.message))) : (React.createElement(React.Fragment, null,
                React.createElement(RepositoryCompareCommitsPage, Object.assign({}, this.props)),
                React.createElement("div", { className: "mb-3" }),
                React.createElement(RepositoryCompareDiffPage, Object.assign({}, this.props, { base: {
                        repoPath: this.props.base.repoPath,
                        repoID: this.props.base.repoID,
                        rev: this.props.base.rev || null,
                        commitID: this.state.rangeOrError.baseRevSpec.object.oid,
                    }, head: {
                        repoPath: this.props.head.repoPath,
                        repoID: this.props.head.repoID,
                        rev: this.props.head.rev || null,
                        commitID: this.state.rangeOrError.headRevSpec.object.oid,
                    }, extensionsController: this.props.extensionsController, extensionsOnVisibleTextDocumentsChange: this.props.extensionsOnVisibleTextDocumentsChange }))))));
    }
}
//# sourceMappingURL=RepositoryCompareOverviewPage.js.map