import { upperFirst } from 'lodash';
import ExportIcon from 'mdi-react/ExportIcon';
import GithubCircleIcon from 'mdi-react/GithubCircleIcon';
import * as React from 'react';
import { merge, of, Subject, Subscription } from 'rxjs';
import { catchError, distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators';
import { ActionItem } from '../../components/ActionItem';
import { asError, isErrorLike } from '../../util/errors';
import { PhabricatorIcon } from '../../util/icons'; // TODO: Switch mdi icon
import { fetchFileExternalLinks } from '../backend';
/**
 * A repository header action that goes to the corresponding URL on an external code host.
 */
export class GoToCodeHostAction extends React.PureComponent {
    constructor() {
        super(...arguments);
        this.state = { fileExternalLinksOrError: null };
        this.componentUpdates = new Subject();
        this.subscriptions = new Subscription();
    }
    componentDidMount() {
        this.subscriptions.add(this.componentUpdates
            .pipe(startWith(this.props), distinctUntilChanged((a, b) => a.repo === b.repo && a.rev === b.rev && a.filePath === b.filePath), switchMap(({ repo, rev, filePath }) => {
            if (!repo || !filePath) {
                return of({ fileExternalLinksOrError: null });
            }
            return merge(of({ fileExternalLinksOrError: undefined }), fetchFileExternalLinks({ repoPath: repo.name, rev, filePath }).pipe(catchError(err => [asError(err)]), map(c => ({ fileExternalLinksOrError: c }))));
        }))
            .subscribe(stateUpdate => this.setState(stateUpdate), err => console.error(err)));
    }
    componentWillReceiveProps(props) {
        this.componentUpdates.next(props);
    }
    componentWillUnmount() {
        this.subscriptions.unsubscribe();
    }
    render() {
        if (!this.props.repo) {
            return null;
        }
        let externalURLs;
        if (this.props.externalLinks && this.props.externalLinks.length > 0) {
            externalURLs = this.props.externalLinks;
        }
        else if (this.state.fileExternalLinksOrError === null ||
            this.state.fileExternalLinksOrError === undefined ||
            isErrorLike(this.state.fileExternalLinksOrError) ||
            this.state.fileExternalLinksOrError.length === 0) {
            // If the external link for the more specific resource within the repository is loading or errored, use the
            // repository external link.
            externalURLs = this.props.repo.externalURLs;
        }
        else {
            externalURLs = this.state.fileExternalLinksOrError;
        }
        if (externalURLs.length === 0) {
            return null;
        }
        // Only show the first external link for now.
        const externalURL = externalURLs[0];
        const { displayName, icon } = serviceTypeDisplayNameAndIcon(externalURL.serviceType);
        const Icon = icon || ExportIcon;
        // Special-case for GitHub: add line numbers to URL.
        let url = externalURL.url;
        if (externalURL.serviceType === 'github') {
            if (this.props.range) {
                url += `#L${this.props.range.start.line}-L${this.props.range.end.line}`;
            }
            else if (this.props.position) {
                url += '#L' + this.props.position.line;
            }
        }
        return (React.createElement(ActionItem, { to: url, target: "_self", "data-tooltip": `View on ${displayName}` },
            React.createElement(Icon, { className: "icon-inline" })));
    }
}
function serviceTypeDisplayNameAndIcon(serviceType) {
    switch (serviceType) {
        case 'github':
            return { displayName: 'GitHub', icon: GithubCircleIcon };
        case 'gitlab':
            return { displayName: 'GitLab' };
        case 'bitbucketserver':
            return { displayName: 'Bitbucket Server' };
        case 'phabricator':
            return { displayName: 'Phabricator', icon: PhabricatorIcon };
        case 'awscodecommit':
            return { displayName: 'AWS CodeCommit' };
    }
    return { displayName: serviceType ? upperFirst(serviceType) : 'code host' };
}
//# sourceMappingURL=GoToCodeHostAction.js.map