import { LoadingSpinner } from '@sourcegraph/react-loading-spinner';
import { upperFirst } from 'lodash';
import * as React from 'react';
import { combineLatest, Subject, Subscription } from 'rxjs';
import { catchError, concat, distinctUntilChanged, filter, map, mergeMap, startWith, switchMap, tap, } from 'rxjs/operators';
import { USER_DISPLAY_NAME_MAX_LENGTH } from '..';
import { refreshCurrentUser } from '../../auth';
import { UsernameInput } from '../../auth/SignInSignUpCommon';
import { gql, queryGraphQL } from '../../backend/graphql';
import { Form } from '../../components/Form';
import { PageTitle } from '../../components/PageTitle';
import { eventLogger } from '../../tracking/eventLogger';
import { asError, createAggregateError, isErrorLike } from '../../util/errors';
import { UserAvatar } from '../UserAvatar';
import { updateUser } from './backend';
function queryUser(user) {
    return queryGraphQL(gql `
            query User($user: ID!) {
                node(id: $user) {
                    ... on User {
                        id
                        username
                        displayName
                        avatarURL
                    }
                }
            }
        `, { user }).pipe(map(({ data, errors }) => {
        if (!data || !data.node) {
            throw createAggregateError(errors);
        }
        return data.node;
    }));
}
export class UserAccountProfilePage extends React.Component {
    constructor() {
        super(...arguments);
        this.state = { loading: false, saved: false };
        this.componentUpdates = new Subject();
        this.refreshRequests = new Subject();
        this.submits = new Subject();
        this.subscriptions = new Subscription();
        this.onUsernameFieldChange = (e) => {
            this.setState({ username: e.target.value });
        };
        this.onDisplayNameFieldChange = (e) => {
            this.setState({ displayName: e.target.value });
        };
        this.onAvatarURLFieldChange = (e) => {
            this.setState({ avatarURL: e.target.value });
        };
        this.handleSubmit = (event) => {
            this.submits.next(event);
        };
        this.handleError = (err) => {
            console.error(err);
            this.setState({ loading: false, saved: false, error: err });
            return [];
        };
    }
    componentDidMount() {
        eventLogger.logViewEvent('UserProfile');
        const userChanges = this.componentUpdates.pipe(distinctUntilChanged((a, b) => a.user.id === b.user.id), map(({ user }) => user));
        // Reset the fields upon navigation to a different user.
        this.subscriptions.add(userChanges.subscribe(() => this.setState({
            userOrError: undefined,
            loading: false,
            saved: false,
            username: undefined,
            displayName: undefined,
            avatarURL: undefined,
        })));
        // Fetch the user with all of the fields we need (Props.user might not have them all).
        this.subscriptions.add(combineLatest(userChanges, this.refreshRequests.pipe(startWith(void 0)))
            .pipe(switchMap(([user]) => queryUser(user.id).pipe(catchError(error => [asError(error)]), map(c => ({ userOrError: c })))))
            .subscribe(stateUpdate => this.setState(stateUpdate), err => console.error(err)));
        this.subscriptions.add(this.submits
            .pipe(tap(event => {
            event.preventDefault();
            eventLogger.log('UpdateUserClicked');
        }), filter(event => event.currentTarget.checkValidity()), tap(() => this.setState({ loading: true })), mergeMap(event => updateUser(this.props.user.id, {
            username: this.state.username === undefined ? null : this.state.username,
            displayName: this.state.displayName === undefined ? null : this.state.displayName,
            avatarURL: this.state.avatarURL === undefined ? null : this.state.avatarURL,
        }).pipe(catchError(this.handleError))), tap(() => {
            this.setState({ loading: false, saved: true });
            this.props.onDidUpdateUser();
            // Handle when username changes.
            if (this.state.username !== undefined && this.state.username !== this.props.user.username) {
                this.props.history.push(`/users/${this.state.username}/settings/profile`);
                return;
            }
            this.refreshRequests.next();
            setTimeout(() => this.setState({ saved: false }), 500);
        }), 
        // In case the edited user is the current user, immediately reflect the changes in the UI.
        mergeMap(() => refreshCurrentUser().pipe(concat([null]))))
            .subscribe(undefined, this.handleError));
        this.componentUpdates.next(this.props);
    }
    componentWillReceiveProps(nextProps) {
        this.componentUpdates.next(nextProps);
    }
    componentWillUnmount() {
        this.subscriptions.unsubscribe();
    }
    render() {
        return (React.createElement("div", { className: "user-settings-profile-page" },
            React.createElement(PageTitle, { title: "Profile" }),
            React.createElement("h2", null, "Profile"),
            isErrorLike(this.state.userOrError) && (React.createElement("p", { className: "alert alert-danger" },
                "Error: ",
                upperFirst(this.state.userOrError.message))),
            this.state.error && (React.createElement("p", { className: "alert alert-danger" },
                "Error: ",
                upperFirst(this.state.error.message))),
            this.state.userOrError &&
                !isErrorLike(this.state.userOrError) && (React.createElement(Form, { className: "user-settings-profile-page__form", onSubmit: this.handleSubmit },
                React.createElement("div", { className: "form-group" },
                    React.createElement("label", { htmlFor: "user-settings-profile-page__form-username" }, "Username"),
                    React.createElement(UsernameInput, { id: "user-settings-profile-page__form-username", value: this.state.username === undefined
                            ? this.state.userOrError.username
                            : this.state.username, onChange: this.onUsernameFieldChange, required: true, disabled: this.state.loading, "aria-describedby": "user-settings-profile-page__form-username-help" }),
                    React.createElement("small", { id: "user-settings-profile-page__form-username-help", className: "form-text text-muted" }, "A username consists of letters, numbers, hyphens (-) and may not begin or end with a hyphen")),
                React.createElement("div", { className: "form-group" },
                    React.createElement("label", { htmlFor: "user-settings-profile-page__form-display-name" }, "Display name"),
                    React.createElement("input", { id: "user-settings-profile-page__form-display-name", type: "text", className: "form-control", value: this.state.displayName === undefined
                            ? this.state.userOrError.displayName || ''
                            : this.state.displayName, onChange: this.onDisplayNameFieldChange, disabled: this.state.loading, spellCheck: false, placeholder: "Display name", maxLength: USER_DISPLAY_NAME_MAX_LENGTH })),
                React.createElement("div", { className: "user-settings-profile-page__avatar-row" },
                    React.createElement("div", { className: "form-group user-settings-profile-page__field-column" },
                        React.createElement("label", { htmlFor: "user-settings-profile-page__form-avatar-url" }, "Avatar URL"),
                        React.createElement("input", { id: "user-settings-profile-page__form-avatar-url", type: "url", className: "form-control", value: this.state.avatarURL === undefined
                                ? this.state.userOrError.avatarURL || ''
                                : this.state.avatarURL, onChange: this.onAvatarURLFieldChange, disabled: this.state.loading, spellCheck: false, placeholder: "URL to avatar photo" })),
                    this.state.userOrError.avatarURL && (React.createElement("div", { className: "user-settings-profile-page__avatar-column" },
                        React.createElement(UserAvatar, { user: this.state.userOrError.avatarURL
                                ? { avatarURL: this.state.userOrError.avatarURL }
                                : undefined })))),
                React.createElement("button", { className: "btn btn-primary user-settings-profile-page__button", type: "submit", disabled: this.state.loading }, "Update profile"),
                this.state.loading && (React.createElement("div", null,
                    React.createElement(LoadingSpinner, { className: "icon-inline" }))),
                this.state.saved && (React.createElement("p", { className: "alert alert-success user-settings-profile-page__alert" }, "Profile saved!")),
                window.context.sourcegraphDotComMode && (React.createElement("p", { className: "mt-4" },
                    React.createElement("a", { href: "https://about.sourcegraph.com/contact" }, "Contact support"),
                    " to delete your account."))))));
    }
}
//# sourceMappingURL=UserAccountProfilePage.js.map