import React from 'react';
import SvgImage from 'app/components/elements/SvgImage';
import LoadingIndicator from 'app/components/elements/LoadingIndicator';
import PasswordInput from 'app/components/elements/PasswordInput';
import constants from 'app/redux/constants';
import tt from 'counterpart';
import { FormattedHTMLMessage } from 'app/Translator';
import { APP_DOMAIN, APP_NAME, SUPPORT_EMAIL } from 'app/client_config';
import {PrivateKey} from 'steem/lib/auth/ecc';
import {api} from 'steem';

const email_regex = /^([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22))*\x40([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d))*$/;

function passwordToOwnerPubKey(account_name, password) {
    let pub_key;
    try {
        pub_key = PrivateKey.fromWif(password);
    } catch(e) {
        pub_key = PrivateKey.fromSeed(account_name + 'owner' + password);
    }
    return pub_key.toPublicKey().toString();
}

class RecoverAccountStep1 extends React.Component {

    static propTypes = {
    };

    constructor(props) {
        super(props);
        this.state = {
            name: '',
            name_error: '',
            email: '',
            email_error: '',
            error: '',
            progress_status: '',
            password: {value: '', valid: false},
            show_social_login: '',
            email_submitted: false
        };
        this.onNameChange = this.onNameChange.bind(this);
        this.onEmailChange = this.onEmailChange.bind(this);
        this.onPasswordsChange = this.onPasswordsChange.bind(this);
        this.onSubmit = this.onSubmit.bind(this);
        this.onSubmitEmail = this.onSubmitEmail.bind(this);
    }

    onNameChange(e) {
        const name = e.target.value.trim().toLowerCase();
        this.validateAccountName(name);
        this.setState({name, error: ''});
    }

    onEmailChange(e) {
        const email = e.target.value.trim().toLowerCase();
        let email_error = '';
        if (!email_regex.test(email.toLowerCase())) email_error = tt('recoveraccountstep1_jsx.not_valid');
        this.setState({email, email_error});
    }

    validateAccountName(name) {
        if (!name) return;
        api.getAccountsAsync([name]).then(res => {
            this.setState({name_error: !res || res.length === 0 ? tt('recoveraccountstep1_jsx.account_name_is_not_found') : ''});
            if(res.length) {
                const [account] = res
                // if your last owner key update is prior to July 14th then the old key will not be able to recover
                const ownerUpdate = /Z$/.test(account.last_owner_update) ? account.last_owner_update : account.last_owner_update + 'Z'
                const ownerUpdateTime = new Date(ownerUpdate).getTime()
                const THIRTY_DAYS_AGO = new Date(Date.now() - (30 * 24 * 60 * 60 * 1000)).getTime()
                if(ownerUpdateTime < Math.max(THIRTY_DAYS_AGO, constants.JULY_14_HACK))
                    this.setState({name_error: tt('recoveraccountstep1_jsx.unable_to_recover_account_not_change_ownership_recently')})
            }
        })
    }

    validateAccountOwner(name) {
        const oldOwner = passwordToOwnerPubKey(name, this.state.password.value);
        return api.getOwnerHistoryAsync(name).then(history => {
            const res = history.filter(a => {
                const owner = a.previous_owner_authority.key_auths[0][0];
                return owner === oldOwner;
            });
            return res.length > 0;
        });
    }

    getAccountIdentityProviders(name, owner_key) {
        return fetch('/api/v1/account_identity_providers', {
            method: 'post',
            mode: 'no-cors',
            credentials: 'same-origin',
            headers: {
                Accept: 'application/json',
                'Content-type': 'application/json'
            },
            body: JSON.stringify({csrf: $STM_csrf, name, owner_key})
        }).then(r => r.json()).then(res => {
            console.log('-- validateOffchainAccount -->', res);
            return res.error ? 'email' : res.provider;
        });
    }

    onPasswordsChange({oldPassword, valid}) {
        this.setState({password: {value: oldPassword, valid}, error: ''});
    }

    onSubmit(e) {
        e.preventDefault();
        const owner_key = passwordToOwnerPubKey(this.state.name, this.state.password.value);
        this.validateAccountOwner(this.state.name).then(result => {
            if (result) {
                this.getAccountIdentityProviders(this.state.name, owner_key).then(provider => {
                    this.setState({show_social_login: provider});
                });
            }
            else this.setState({error: tt('recoveraccountstep1_jsx.password_not_used_in_last_days')});
        });
    }

    onSubmitEmail(e) {
        e.preventDefault();
        const {name, password} = this.state;
        const owner_key = passwordToOwnerPubKey(name, password.value);
        fetch('/api/v1/initiate_account_recovery_with_email', {
            method: 'post',
            mode: 'no-cors',
            credentials: 'same-origin',
            headers: {
                Accept: 'application/json',
                'Content-type': 'application/json'
            },
            body: JSON.stringify({
                csrf: $STM_csrf,
                contact_email: this.state.email,
                account_name: name,
                owner_key
            })
        }).then(r => r.json()).then(res => {
            if (res.error) {
                this.setState({email_error: res.error || 'Unknown'});
            } else {
                if (res.status === 'ok') {
                    this.setState({email_submitted: true});
                }
                if (res.status === 'duplicate') {
                    this.setState({email_error: tt('recoveraccountstep1_jsx.request_already_submitted_contact_support', {SUPPORT_EMAIL})});
                }
            }
        }).catch(error => {
            console.error('request_account_recovery server error (2)', error);
            this.setState({email_error: (error.message ? error.message : error)});
        });
    }

    render() {
        const {name, name_error, email, email_error, error, progress_status, password, show_social_login, email_submitted} = this.state;
        const owner_key = passwordToOwnerPubKey(name, password.value);
        const valid = name && !name_error && password.valid;
        const submit_btn_class = 'button action' + (!valid ? ' disabled' : '');
        const show_account_and_passwords = !email_submitted && !show_social_login;
        return (
            <div className="RestoreAccount SignUp">
                {show_account_and_passwords && <div className="row">
                    <div className="column large-4">
                        <h2>{tt('navigation.stolen_account_recovery')}</h2>
                        <p>
                            {tt('recoveraccountstep1_jsx.recover_account_intro', {APP_URL: APP_DOMAIN, APP_NAME})}
                        </p>
                        <form onSubmit={this.onSubmit} noValidate>
                            <div className={name_error ? 'error' : ''}>
                                <label>
                                    {tt('g.account_name')}
                                    <input type="text" name="name" autoComplete="off" onChange={this.onNameChange} value={name} />
                                </label>
                                <p className="error">{name_error}</p>
                            </div>
                            <PasswordInput passwordLabel={tt('g.recent_password')} onChange={this.onPasswordsChange} />
                            <br />
                            <div className="error">{error}</div>
                            {progress_status ? <span><LoadingIndicator type="circle" inline /> {progress_status}</span>
                        : <input disabled={!valid} type="submit" className={submit_btn_class} value= {tt('recoveraccountstep1_jsx.begin_recovery')} />}
                        </form>
                    </div>
                </div>}

                {show_social_login && show_social_login !== 'email' &&
                <form action="/initiate_account_recovery" method="post">
                    <input type="hidden" name="csrf" value={$STM_csrf} />
                    <input type="hidden" name="account_name" value={name} />
                    <input type="hidden" name="owner_key" value={owner_key} />
                    <div className="row">
                        <div className="column large-4">
                            {show_social_login === 'both' ? <p>{tt('recoveraccountstep1_jsx.login_with_facebook_or_reddit_media_to_verify_identity')}.</p>
                        : <p>{tt('recoveraccountstep1_jsx.login_with_social_media_to_verify_identity', {
                            provider: show_social_login.charAt(0).toUpperCase() + show_social_login.slice(1)
                        })}.</p>}
                        </div>
                    </div>
                    <div className="row">
                        &nbsp;
                    </div>
                    {(show_social_login === 'both' || show_social_login === 'facebook') && <div className="row">
                        <div className="column large-4 shrink">
                            <SvgImage name="facebook" width="64px" height="64px" />
                        </div>
                        <div className="column large-8">
                            <input type="submit" name="provider" value="facebook" className="button SignUp--fb-button" />
                        </div>
                    </div>}
                    <div className="row">
                        &nbsp;
                    </div>
                    {(show_social_login === 'both' || show_social_login === 'reddit') && <div className="row">
                        <div className="column large-4 shrink">
                            <SvgImage name="reddit" width="64px" height="64px" />
                        </div>
                        <div className="column large-8">
                            <input type="submit" name="provider" value="reddit" className="button SignUp--reddit-button" />
                        </div>
                    </div>}
                    <div className="row">
                        <div className="column">&nbsp;</div>
                    </div>
                </form>
                }
                {show_social_login && show_social_login === 'email' &&
                    <div className="row">
                        <div className="column large-4">
                            {
                                email_submitted
                                    ? tt('recoveraccountstep1_jsx.thanks_for_submitting_request_for_account_recovery', {APP_NAME})
                                    : <form onSubmit={this.onSubmitEmail} noValidate>
                                    <p>{tt('recoveraccountstep1_jsx.enter_email_toverify_identity')}</p>
                                    <div className={email_error ? 'column large-4 shrink error' : 'column large-4 shrink'}>
                                        <label>{tt('g.email')}
                                            <input type="text" name="email" autoComplete="off" onChange={this.onEmailChange} value={email} />
                                        </label>
                                        <p className="error">{email_error}</p>
                                        <input type="submit" disabled={email_error || !email} className="button hollow"
                                               value={tt('recoveraccountstep1_jsx.continue_with_email')} />
                                    </div>
                                </form>
                            }
                        </div>
                    </div>
                }
            </div>
        );
    }
}

module.exports = {
    path: 'recover_account_step_1',
    component: RecoverAccountStep1
};

