import { LoadingSpinner } from '@sourcegraph/react-loading-spinner';
import { upperFirst } from 'lodash';
import KeyIcon from 'mdi-react/KeyIcon';
import * as React from 'react';
import { Link } from 'react-router-dom';
import { Form } from '../components/Form';
import { HeroPage } from '../components/HeroPage';
import { PageTitle } from '../components/PageTitle';
import { eventLogger } from '../tracking/eventLogger';
import { asError, isErrorLike } from '../util/errors';
import { PasswordInput } from './SignInSignUpCommon';
/**
 * A form where the user can initiate the reset-password flow. This is the 1st step in the
 * reset-password flow; ResetPasswordCodePage is the 2nd step.
 */
class ResetPasswordInitForm extends React.PureComponent {
    constructor() {
        super(...arguments);
        this.state = {
            email: '',
            submitOrError: undefined,
        };
        this.onEmailFieldChange = (e) => {
            this.setState({ email: e.target.value });
        };
        this.handleSubmitResetPasswordInit = (e) => {
            e.preventDefault();
            this.setState({ submitOrError: 'loading' });
            fetch('/-/reset-password-init', {
                credentials: 'same-origin',
                method: 'POST',
                headers: Object.assign({}, window.context.xhrHeaders, { 'Content-Type': 'application/json' }),
                body: JSON.stringify({
                    email: this.state.email,
                }),
            })
                .then(resp => {
                if (resp.status === 200) {
                    this.setState({ submitOrError: null });
                }
                else if (resp.status === 429) {
                    this.setState({
                        submitOrError: new Error('Too many password reset requests. Try again in a few minutes.'),
                    });
                }
                else {
                    resp.text()
                        .catch(err => null)
                        .then(text => this.setState({ submitOrError: new Error(text || 'Unknown error') }))
                        .catch(err => console.error(err));
                }
            })
                .catch(err => this.setState({ submitOrError: asError(err) }));
        };
    }
    render() {
        if (this.state.submitOrError === null) {
            return React.createElement("div", { className: "alert alert-success" }, "Password reset email sent.");
        }
        return (React.createElement(Form, { className: "reset-password-page__form", onSubmit: this.handleSubmitResetPasswordInit },
            React.createElement("p", null, "Enter the email address associated with your account. You'll receive an email with a link to reset your password."),
            React.createElement("div", { className: "form-group" },
                React.createElement("input", { className: "form-control", onChange: this.onEmailFieldChange, value: this.state.email, type: "email", name: "email", autoFocus: true, spellCheck: false, placeholder: "Email", required: true, autoComplete: "email", disabled: this.state.submitOrError === 'loading' })),
            React.createElement("button", { className: "btn btn-primary btn-block", type: "submit", disabled: this.state.submitOrError === 'loading' }, "Send reset password link"),
            this.state.submitOrError === 'loading' && React.createElement(LoadingSpinner, { className: "icon-inline mt-2" }),
            isErrorLike(this.state.submitOrError) && (React.createElement("div", { className: "alert alert-danger mt-2" }, upperFirst(this.state.submitOrError.message)))));
    }
}
class ResetPasswordCodeForm extends React.PureComponent {
    constructor() {
        super(...arguments);
        this.state = {
            password: '',
            submitOrError: undefined,
        };
        this.onPasswordFieldChange = (e) => {
            this.setState({ password: e.target.value });
        };
        this.handleSubmitResetPassword = (e) => {
            e.preventDefault();
            this.setState({ submitOrError: 'loading' });
            fetch('/-/reset-password-code', {
                credentials: 'same-origin',
                method: 'POST',
                headers: Object.assign({}, window.context.xhrHeaders, { 'Content-Type': 'application/json' }),
                body: JSON.stringify({
                    userID: this.props.userID,
                    code: this.props.code,
                    password: this.state.password,
                }),
            })
                .then(resp => {
                if (resp.status === 200) {
                    this.setState({ submitOrError: null });
                }
                else if (resp.status === 401) {
                    this.setState({ submitOrError: new Error('Password reset code was invalid or expired.') });
                }
                else {
                    this.setState({ submitOrError: new Error('Password reset failed.') });
                }
            })
                .catch(err => this.setState({ submitOrError: asError(err) }));
        };
    }
    render() {
        if (this.state.submitOrError === null) {
            return (React.createElement("div", { className: "alert alert-success" },
                "Your password was reset. ",
                React.createElement(Link, { to: "/sign-in" }, "Sign in with your new password"),
                " to continue."));
        }
        return (React.createElement(Form, { className: "reset-password-page__form", onSubmit: this.handleSubmitResetPassword },
            React.createElement("p", null, "Enter a new password for your account."),
            React.createElement("div", { className: "form-group" },
                React.createElement(PasswordInput, { name: "password", onChange: this.onPasswordFieldChange, value: this.state.password, required: true, autoFocus: true, autoComplete: "new-password", disabled: this.state.submitOrError === 'loading' })),
            React.createElement("button", { className: "btn btn-primary btn-block", type: "submit", disabled: this.state.submitOrError === 'loading' }, "Reset password"),
            this.state.submitOrError === 'loading' && React.createElement(LoadingSpinner, { className: "icon-inline mt-2" }),
            isErrorLike(this.state.submitOrError) && (React.createElement("div", { className: "alert alert-danger mt-2" }, upperFirst(this.state.submitOrError.message)))));
    }
}
/**
 * A page that implements the reset-password flow for a user: (1) initiate the flow by providing the email address
 * of the account whose password to reset, and (2) complete the flow by providing the password-reset code.
 */
export class ResetPasswordPage extends React.PureComponent {
    componentDidMount() {
        eventLogger.logViewEvent('ResetPassword', {}, false);
    }
    render() {
        let body;
        if (this.props.user) {
            body = React.createElement("div", { className: "alert alert-danger" }, "Authenticated users may not perform password reset.");
        }
        else if (window.context.resetPasswordEnabled) {
            const searchParams = new URLSearchParams(this.props.location.search);
            if (searchParams.has('code') || searchParams.has('userID')) {
                const code = searchParams.get('code');
                const userID = parseInt(searchParams.get('userID') || '', 10);
                if (code && typeof userID === 'number' && !isNaN(userID)) {
                    body = React.createElement(ResetPasswordCodeForm, { code: code, userID: userID });
                }
                else {
                    body = React.createElement("div", { className: "alert alert-danger" }, "The password reset link you followed is invalid.");
                }
            }
            else {
                body = React.createElement(ResetPasswordInitForm, null);
            }
        }
        else {
            body = (React.createElement("div", { className: "alert alert-warning" }, "Password reset is disabled. Ask a site administrator to manually reset your password."));
        }
        return (React.createElement(React.Fragment, null,
            React.createElement(PageTitle, { title: "Reset password" }),
            React.createElement(HeroPage, { icon: KeyIcon, title: "Reset password", cta: body })));
    }
}
//# sourceMappingURL=ResetPasswordPage.js.map