import { upperFirst } from 'lodash';
import AlertCircleIcon from 'mdi-react/AlertCircleIcon';
import * as React from 'react';
import { defer, Subject, Subscription } from 'rxjs';
import { catchError, delay, distinctUntilChanged, map, retryWhen, switchMap, tap } from 'rxjs/operators';
import { HeroPage } from '../components/HeroPage';
import { displayRepoPath } from '../components/RepoFileLink';
import { isErrorLike } from '../util/errors';
import { RepoQuestionIcon } from '../util/icons';
import { RepositoryIcon } from '../util/icons'; // TODO: Switch to mdi icon
import { ECLONEINPROGESS, EREVNOTFOUND, resolveRev } from './backend';
import { DirectImportRepoAlert } from './DirectImportRepoAlert';
export const RepositoryCloningInProgressPage = ({ repoName, progress, }) => (React.createElement(HeroPage, { icon: RepositoryIcon, title: displayRepoPath(repoName), className: "repository-cloning-in-progress-page", subtitle: "Cloning in progress", detail: React.createElement("code", null, progress), body: React.createElement(DirectImportRepoAlert, { className: "mt-3" }) }));
export const EmptyRepositoryPage = () => React.createElement(HeroPage, { icon: RepoQuestionIcon, title: "Empty repository" });
/**
 * A container for a repository page that incorporates global Git data but is not tied to one specific revision. A
 * loading/error page is shown if the repository is not yet cloned or is empty. Otherwise, the children are
 * rendered.
 */
export class RepositoryGitDataContainer extends React.PureComponent {
    constructor() {
        super(...arguments);
        this.state = {};
        this.propsUpdates = new Subject();
        this.subscriptions = new Subscription();
    }
    componentDidMount() {
        // Fetch repository revision.
        this.subscriptions.add(this.propsUpdates
            .pipe(map(({ repoPath }) => repoPath), distinctUntilChanged(), tap(() => this.setState({ gitDataPresentOrError: undefined })), switchMap(repoPath => defer(() => resolveRev({ repoPath })).pipe(
        // On a CloneInProgress error, retry after 1s
        retryWhen(errors => errors.pipe(tap(error => {
            switch (error.code) {
                case ECLONEINPROGESS:
                    // Display cloning screen to the user and retry
                    this.setState({ gitDataPresentOrError: error });
                    return;
                default:
                    // Display error to the user and do not retry
                    throw error;
            }
        }), delay(1000))), 
        // Save any error in the state to display to the user
        catchError(error => {
            this.setState({ gitDataPresentOrError: error });
            return [];
        }))))
            .subscribe(resolvedRev => this.setState({ gitDataPresentOrError: true }), error => console.error(error)));
        this.propsUpdates.next(this.props);
    }
    componentWillReceiveProps(props) {
        this.propsUpdates.next(props);
    }
    componentWillUnmount() {
        this.subscriptions.unsubscribe();
    }
    render() {
        if (!this.state.gitDataPresentOrError) {
            // Render nothing while loading
            return null;
        }
        if (isErrorLike(this.state.gitDataPresentOrError)) {
            // Show error page
            switch (this.state.gitDataPresentOrError.code) {
                case ECLONEINPROGESS:
                    return (React.createElement(RepositoryCloningInProgressPage, { repoName: this.props.repoPath, progress: this.state.gitDataPresentOrError.progress }));
                case EREVNOTFOUND:
                    return React.createElement(EmptyRepositoryPage, null);
                default:
                    return (React.createElement(HeroPage, { icon: AlertCircleIcon, title: "Error", subtitle: upperFirst(this.state.gitDataPresentOrError.message) }));
            }
        }
        return this.props.children;
    }
}
//# sourceMappingURL=RepositoryGitDataContainer.js.map