import { LoadingSpinner } from '@sourcegraph/react-loading-spinner';
import { upperFirst } from 'lodash';
import * as React from 'react';
import { Link, Redirect } from 'react-router-dom';
import { concat, Subject, Subscription } from 'rxjs';
import { catchError, concatMap, distinctUntilKeyChanged, map, tap, withLatestFrom } from 'rxjs/operators';
import { orgURL } from '..';
import { refreshCurrentUser } from '../../auth';
import { gql, mutateGraphQL } from '../../backend/graphql';
import { Form } from '../../components/Form';
import { ModalPage } from '../../components/ModalPage';
import { PageTitle } from '../../components/PageTitle';
import { eventLogger } from '../../tracking/eventLogger';
import { userURL } from '../../user';
import { asError, createAggregateError, isErrorLike } from '../../util/errors';
import { OrgAvatar } from '../OrgAvatar';
/**
 * Displays the organization invitation for the current user, if any.
 */
export class OrgInvitationPage extends React.PureComponent {
    constructor() {
        super(...arguments);
        this.state = {};
        this.componentUpdates = new Subject();
        this.responses = new Subject();
        this.subscriptions = new Subscription();
        this.onAcceptInvitation = e => {
            e.preventDefault();
            this.responses.next("ACCEPT" /* ACCEPT */);
        };
        this.onDeclineInvitation = e => {
            e.preventDefault();
            this.responses.next("REJECT" /* REJECT */);
        };
        this.respondToOrganizationInvitation = (args) => mutateGraphQL(gql `
                mutation RespondToOrganizationInvitation(
                    $organizationInvitation: ID!
                    $responseType: OrganizationInvitationResponseType!
                ) {
                    respondToOrganizationInvitation(
                        organizationInvitation: $organizationInvitation
                        responseType: $responseType
                    ) {
                        alwaysNil
                    }
                }
            `, args).pipe(map(({ data, errors }) => {
            if (!data || !data.respondToOrganizationInvitation) {
                throw createAggregateError(errors);
            }
            return;
        }));
    }
    componentDidMount() {
        eventLogger.logViewEvent('OrgInvitation');
        const orgChanges = this.componentUpdates.pipe(distinctUntilKeyChanged('org'), map(({ org }) => org));
        this.subscriptions.add(this.responses
            .pipe(withLatestFrom(orgChanges), concatMap(([responseType, org]) => concat([
            {
                submissionOrError: 'loading',
                lastResponse: responseType,
            },
        ], this.respondToOrganizationInvitation({
            organizationInvitation: org.viewerPendingInvitation.id,
            responseType,
        }).pipe(tap(() => eventLogger.log('OrgInvitationRespondedTo')), tap(() => this.props.onDidRespondToInvitation()), concatMap(() => [
            // Refresh current user's list of organizations.
            refreshCurrentUser(),
            { submissionOrError: null },
        ]), catchError(err => [{ submissionOrError: asError(err) }])))))
            .subscribe(stateUpdate => this.setState(stateUpdate), err => console.error(err)));
        this.componentUpdates.next(this.props);
    }
    componentWillReceiveProps(props) {
        this.componentUpdates.next(props);
    }
    componentWillUnmount() {
        this.subscriptions.unsubscribe();
    }
    render() {
        // Redirect unauthenticated users to sign-in.
        if (!this.props.authenticatedUser) {
            const newUrl = new URL(window.location.href);
            newUrl.pathname = '/sign-in';
            // Return to the current page after sign up/in.
            newUrl.searchParams.set('returnTo', window.location.href);
            return React.createElement(Redirect, { to: newUrl.pathname + newUrl.search });
        }
        if (this.state.submissionOrError === null) {
            // Go to organization profile after accepting invitation, or user's own profile after declining
            // invitation.
            return (React.createElement(Redirect, { to: this.state.lastResponse
                    ? orgURL(this.props.org.name)
                    : userURL(this.props.authenticatedUser.username) }));
        }
        return (React.createElement(React.Fragment, null,
            React.createElement(PageTitle, { title: `Invitation - ${this.props.org.name}` }),
            this.props.org.viewerPendingInvitation ? (React.createElement(ModalPage, { icon: React.createElement(OrgAvatar, { org: this.props.org.name, className: "mt-2 mb-3", size: "lg" }) },
                React.createElement(Form, { className: "text-center" },
                    React.createElement("h3", { className: "my-0 font-weight-normal" },
                        "You've been invited to the",
                        ' ',
                        React.createElement(Link, { to: orgURL(this.props.org.name) },
                            React.createElement("strong", null, this.props.org.name)),
                        ' ',
                        "organization."),
                    React.createElement("p", null,
                        React.createElement("small", { className: "text-muted" },
                            "Invited by",
                            ' ',
                            React.createElement(Link, { to: userURL(this.props.org.viewerPendingInvitation.sender.username) }, this.props.org.viewerPendingInvitation.sender.username))),
                    React.createElement("div", { className: "mt-3" },
                        React.createElement("button", { type: "submit", className: "btn btn-primary mr-sm-2", disabled: this.state.submissionOrError === 'loading', onClick: this.onAcceptInvitation },
                            "Join ",
                            this.props.org.name),
                        React.createElement(Link, { className: "btn btn-outline-link", to: orgURL(this.props.org.name) },
                            "Go to ",
                            this.props.org.name,
                            "'s profile")),
                    React.createElement("div", null,
                        React.createElement("button", { className: "btn btn-link btn-sm", disabled: this.state.submissionOrError === 'loading', onClick: this.onDeclineInvitation }, "Decline invitation")),
                    isErrorLike(this.state.submissionOrError) && (React.createElement("div", { className: "alert alert-danger my-2" }, upperFirst(this.state.submissionOrError.message))),
                    this.state.submissionOrError === 'loading' && React.createElement(LoadingSpinner, { className: "icon-inline" })))) : (React.createElement("div", { className: "alert alert-danger" }, "No pending invitation found."))));
    }
}
//# sourceMappingURL=OrgInvitationPage.js.map