import { isEqual } from 'lodash';
import AddIcon from 'mdi-react/AddIcon';
import DeleteIcon from 'mdi-react/DeleteIcon';
import SettingsIcon from 'mdi-react/SettingsIcon';
import * as React from 'react';
import { Link } from 'react-router-dom';
import { merge, of, Subject, Subscription } from 'rxjs';
import { catchError, distinctUntilChanged, map, switchMap } from 'rxjs/operators';
import { CopyableText } from '../components/CopyableText';
import { FilteredConnection } from '../components/FilteredConnection';
import { PageTitle } from '../components/PageTitle';
import { eventLogger } from '../tracking/eventLogger';
import { userURL } from '../user';
import { setUserEmailVerified } from '../user/account/backend';
import { asError } from '../util/errors';
import { deleteUser, fetchAllUsers, randomizeUserPassword, setUserIsSiteAdmin } from './backend';
class UserNode extends React.PureComponent {
    constructor() {
        super(...arguments);
        this.state = {
            loading: false,
        };
        this.emailVerificationClicks = new Subject();
        this.subscriptions = new Subscription();
        this.promoteToSiteAdmin = () => this.setSiteAdmin(true);
        this.demoteFromSiteAdmin = () => this.setSiteAdmin(false);
        this.randomizePassword = () => {
            if (!window.confirm(`Reset the password for ${this.props.node.username} to a random password? The user must reset their password to sign in again.`)) {
                return;
            }
            this.setState({
                errorDescription: undefined,
                resetPasswordURL: undefined,
                loading: true,
            });
            randomizeUserPassword(this.props.node.id)
                .toPromise()
                .then(({ resetPasswordURL }) => {
                this.setState({
                    loading: false,
                    resetPasswordURL,
                });
            }, err => this.setState({ loading: false, errorDescription: err.message }));
        };
        this.deleteUser = () => {
            if (!window.confirm(`Delete the user ${this.props.node.username}?`)) {
                return;
            }
            this.setState({
                errorDescription: undefined,
                resetPasswordURL: undefined,
                loading: true,
            });
            deleteUser(this.props.node.id)
                .toPromise()
                .then(() => {
                this.setState({ loading: false });
                if (this.props.onDidUpdate) {
                    this.props.onDidUpdate();
                }
            }, err => this.setState({ loading: false, errorDescription: err.message }));
        };
    }
    componentDidMount() {
        this.subscriptions.add(this.emailVerificationClicks
            .pipe(distinctUntilChanged((a, b) => isEqual(a, b)), switchMap(({ email, verified }) => merge(of({
            errorDescription: undefined,
            resetPasswordURL: undefined,
            loading: true,
        }), setUserEmailVerified(this.props.node.id, email, verified).pipe(map(() => ({ loading: false })), catchError(error => [{ loading: false, errorDescription: asError(error).message }])))))
            .subscribe(stateUpdate => {
            this.setState(stateUpdate);
            if (this.props.onDidUpdate) {
                this.props.onDidUpdate();
            }
        }, err => console.error(err)));
    }
    componentWillUnmount() {
        this.subscriptions.unsubscribe();
    }
    render() {
        return (React.createElement("li", { className: "list-group-item py-2" },
            React.createElement("div", { className: "d-flex align-items-center justify-content-between" },
                React.createElement("div", null,
                    React.createElement(Link, { to: `/users/${this.props.node.username}` },
                        React.createElement("strong", null, this.props.node.username)),
                    React.createElement("br", null),
                    React.createElement("span", { className: "text-muted" }, this.props.node.displayName)),
                React.createElement("div", null,
                    React.createElement(Link, { className: "btn btn-sm btn-secondary", to: `${userURL(this.props.node.username)}/settings` },
                        React.createElement(SettingsIcon, { className: "icon-inline" }),
                        " Settings"),
                    ' ',
                    window.context.resetPasswordEnabled && (React.createElement("button", { className: "btn btn-sm btn-secondary", onClick: this.randomizePassword, disabled: this.state.loading || !!this.state.resetPasswordURL }, "Reset password")),
                    ' ',
                    this.props.node.id !== this.props.currentUser.id &&
                        (this.props.node.siteAdmin ? (React.createElement("button", { className: "btn btn-sm btn-secondary", onClick: this.demoteFromSiteAdmin, disabled: this.state.loading }, "Revoke site admin")) : (React.createElement("button", { key: "promote", className: "btn btn-sm btn-secondary", onClick: this.promoteToSiteAdmin, disabled: this.state.loading }, "Promote to site admin"))),
                    ' ',
                    this.props.node.id !== this.props.currentUser.id && (React.createElement("button", { className: "btn btn-sm btn-danger", onClick: this.deleteUser, disabled: this.state.loading, "data-tooltip": "Delete user" },
                        React.createElement(DeleteIcon, { className: "icon-inline" }))))),
            this.state.errorDescription && (React.createElement("div", { className: "alert alert-danger mt-2" }, this.state.errorDescription)),
            this.state.resetPasswordURL && (React.createElement("div", { className: "alert alert-success mt-2" },
                React.createElement("p", null,
                    "Password was reset. You must manually send ",
                    React.createElement("strong", null, this.props.node.username),
                    " this reset link:"),
                React.createElement(CopyableText, { text: this.state.resetPasswordURL, size: 40 })))));
    }
    setSiteAdmin(siteAdmin) {
        if (!window.confirm(siteAdmin
            ? `Promote user ${this.props.node.username} to site admin?`
            : `Revoke site admin status from user ${this.props.node.username}?`)) {
            return;
        }
        this.setState({
            errorDescription: undefined,
            loading: true,
        });
        setUserIsSiteAdmin(this.props.node.id, siteAdmin)
            .toPromise()
            .then(() => {
            this.setState({ loading: false });
            if (this.props.onDidUpdate) {
                this.props.onDidUpdate();
            }
        }, err => this.setState({ loading: false, errorDescription: err.message }));
    }
}
class FilteredUserConnection extends FilteredConnection {
}
/**
 * A page displaying the users on this site.
 */
export class SiteAdminAllUsersPage extends React.Component {
    constructor() {
        super(...arguments);
        this.state = {};
        this.userUpdates = new Subject();
        this.subscriptions = new Subscription();
        this.onDidUpdateUser = () => this.userUpdates.next();
    }
    componentDidMount() {
        eventLogger.logViewEvent('SiteAdminAllUsers');
    }
    componentWillUnmount() {
        this.subscriptions.unsubscribe();
    }
    render() {
        const nodeProps = {
            currentUser: this.props.user,
            onDidUpdate: this.onDidUpdateUser,
        };
        return (React.createElement("div", { className: "site-admin-all-users-page" },
            React.createElement(PageTitle, { title: "Users - Admin" }),
            React.createElement("h2", null, "Users"),
            React.createElement("div", null,
                React.createElement(Link, { to: "/site-admin/users/new", className: "btn btn-primary" },
                    React.createElement(AddIcon, { className: "icon-inline" }),
                    " Create user account"),
                "\u00A0",
                React.createElement(Link, { to: "/site-admin/configuration", className: "btn btn-secondary" },
                    React.createElement(SettingsIcon, { className: "icon-inline" }),
                    " Configure SSO")),
            React.createElement(FilteredUserConnection, { className: "mt-3", listClassName: "list-group list-group-flush", noun: "user", pluralNoun: "users", queryConnection: fetchAllUsers, nodeComponent: UserNode, nodeComponentProps: nodeProps, updates: this.userUpdates, history: this.props.history, location: this.props.location })));
    }
}
//# sourceMappingURL=SiteAdminAllUsersPage.js.map