<commit_before>/**
 * Created by ksinger on 19.02.2016.
 */

import  won from '../won-es6.js';
import Immutable from 'immutable';
import { actionTypes, actionCreators } from './actions.js';
import { fetchOwnedData } from '../won-message-utils.js';
import {
    registerAccount,
    login,
    privateId2Credentials,
    logout,
    parseCredentials,
} from '../won-utils.js';
import {
    stateGoCurrent,

} from './cstm-router-actions.js';
import {
    resetParams,
    checkAccessToCurrentRoute,
} from '../configRouting.js';

import {
    checkHttpStatus,
    getIn,
} from '../utils.js';

/**
 * @param privateId
 * @param options see `accountLogin`
 * @returns {*}
 */
//export function anonAccountLogin(privateId, options) {
//    const {email, password} = privateId2Credentials(privateId);
//    return (dispatch, getState) => {
//        const state = getState();
//        const options_ = Object.assign(
//            { // defaults
//                fetchData: true,
//                redirectToFeed: false,
//                relogIfNecessary: true, // if there's a valid session or privateId, log out from that first.
//                wasLoggedIn: false,
//            },
//            options
//        );
//
//        let loggedOutPromise;
//        if(
//            options_.relogIfNecessary &&
//            // v--- do any re-login-actions only after initialPageLoad. The latter should handle any necessary logins itself.
//            state.get('initialLoadFinished') &&
//            state.getIn(['router', 'currentParams', 'privateId']) !== privateId
//        ) {
//            // privateId has changed, need to relog
//            options_.wasLoggedIn = true;
//            loggedOutPromise = logoutAndResetPrivateId(dispatch, getState)
//        } else {
//            loggedOutPromise = Promise.resolve();
//        }
//        options_.relogIfNecessary = false; // any necessary logout has been handled
//
//        return loggedOutPromise.then(() =>
//            accountLogin(email, password, options_)(dispatch, getState)
//        );
//    }
//}

let _loginInProcessFor;
/**
 *
 * @param username
 * @param password
 * @param options
 *    * fetchData(true): whether or not to fetch a users owned needs. If the account
 *    signing in is new, there's no need to fetch this and `false` can be passed here
 *    * doRedirects(true): whether or not to do any redirects at all (e.g. if an invalid route was accessed)
 *    * redirectToFeed(false): whether or not to redirect to the feed after signing in (needs `redirects` to be true)
 *    * relogIfNecessary(true):  if there's a valid session or privateId, log out from that first.
 *
 * @param credentials either {email, password} or {privateId}
 * @returns {Function}
 */
export function accountLogin(credentials, options) {
    const options_ = Object.assign(
        { // defaults
            fetchData: true,
            doRedirects: true,
            redirectToFeed: false,
            relogIfNecessary: true, // if there's a valid session or privateId, log out from that first.
        },
        options
    );
    return (dispatch, getState) => {
        const state = getState();

        const {email} = parseCredentials(credentials);

        const prevPrivateId = getIn(state, ['router', 'currentParams', 'privateId']);
        const prevEmail = state.getIn(['user', 'email']);

        const wasLoggedIn = state.get('initialLoadFinished') && (prevPrivateId || prevEmail);

        if(state.get('loginInProcessFor') === email || _loginInProcessFor === email) {
            console.info('Already logging in as ', email, '. Canceling redundant attempt.');
            return;
        }

        if(state.get('initialLoadFinished') && (
             credentials.privateId && credentials.privateId === prevPrivateId ||
             credentials.email && credentials.email === prevEmail
           )
        ) {
                console.info(
                    'Already logged into this account (' +
                    (credentials.privateId || credentials.email) +
                    '). Aborting second login attempt.');
                return;
        }



        return Promise.resolve()
        .then(() => {
            _loginInProcessFor = email;
            return dispatch({
                type: actionTypes.loginStarted,
                payload: {email}
            })
        })
        .then(() => {
            if (wasLoggedIn) {
                return logout()
                .then(() => {
                    if (options_.doRedirects && getIn(state, ['router', 'currentParams', 'privateId'])) {
                        return stateGoCurrent({privateId: ""})(dispatch, getState);
                    }
                });
            }
        })
        .then(() => {
            if(options_.doRedirects && credentials.privateId) {
                return stateGoCurrent({privateId: credentials.privateId})(dispatch, getState);
            }
        })
        .then(() =>
            login(credentials)
        )
        .then(() =>
            dispatch({
                type: actionTypes.login,
                payload: Immutable.fromJS({email: email, loggedIn: true})
            })
        )
        .then(() => {
            if(!options_.doRedirects) {
                return;
            } else if (options_.redirectToFeed) {
                return dispatch(actionCreators.router__stateGoResetParams("feed"))
            } else {
                return checkAccessToCurrentRoute(dispatch, getState);
            }
        })
        .then(response =>
            options_.fetchData ? fetchOwnedData(email) : Immutable.Map() // only need to fetch data for non-new accounts
        )
        .then(allThatData =>
            dispatch({
                type: actionTypes.login,
                payload: allThatData.merge({email: email, loggedIn: true, loginFinished: true})
            })
        )
        .then(() =>
        /**
         * TODO this action is part of the session-upgrade hack documented in:
         * https://github.com/researchstudio-sat/webofneeds/issues/381#issuecomment-172569377
         */
            dispatch(actionCreators.reconnect())
        )
        .catch(error => {
            console.error("accountLogin ErrorObject", error);
            return Promise.resolve()
                .then(() => {
                    if(wasLoggedIn) {
                        return dispatch({
                            type: actionTypes.logout,
                            payload: Immutable.fromJS({loggedIn: false})
                        })
                    }
                })
                .then(() => {
                    const loginError = credentials.privateId ?
                        'invalid privateId' :
                        'unknown username/password combination';

                    dispatch(actionCreators.loginFailed({
                        loginError,
                        error,<commit_msg>Progressive dispatching during login.<commit_after>/**
 * Created by ksinger on 19.02.2016.
 */

import  won from '../won-es6.js';
import Immutable from 'immutable';
import { actionTypes, actionCreators } from './actions.js';
import { fetchOwnedData } from '../won-message-utils.js';
import {
    registerAccount,
    login,
    privateId2Credentials,
    logout,
    parseCredentials,
} from '../won-utils.js';
import {
    stateGoCurrent,

} from './cstm-router-actions.js';
import {
    resetParams,
    checkAccessToCurrentRoute,
} from '../configRouting.js';

import {
    checkHttpStatus,
    getIn,
} from '../utils.js';

/**
 * @param privateId
 * @param options see `accountLogin`
 * @returns {*}
 */
//export function anonAccountLogin(privateId, options) {
//    const {email, password} = privateId2Credentials(privateId);
//    return (dispatch, getState) => {
//        const state = getState();
//        const options_ = Object.assign(
//            { // defaults
//                fetchData: true,
//                redirectToFeed: false,
//                relogIfNecessary: true, // if there's a valid session or privateId, log out from that first.
//                wasLoggedIn: false,
//            },
//            options
//        );
//
//        let loggedOutPromise;
//        if(
//            options_.relogIfNecessary &&
//            // v--- do any re-login-actions only after initialPageLoad. The latter should handle any necessary logins itself.
//            state.get('initialLoadFinished') &&
//            state.getIn(['router', 'currentParams', 'privateId']) !== privateId
//        ) {
//            // privateId has changed, need to relog
//            options_.wasLoggedIn = true;
//            loggedOutPromise = logoutAndResetPrivateId(dispatch, getState)
//        } else {
//            loggedOutPromise = Promise.resolve();
//        }
//        options_.relogIfNecessary = false; // any necessary logout has been handled
//
//        return loggedOutPromise.then(() =>
//            accountLogin(email, password, options_)(dispatch, getState)
//        );
//    }
//}

let _loginInProcessFor;
/**
 *
 * @param username
 * @param password
 * @param options
 *    * fetchData(true): whether or not to fetch a users owned needs. If the account
 *    signing in is new, there's no need to fetch this and `false` can be passed here
 *    * doRedirects(true): whether or not to do any redirects at all (e.g. if an invalid route was accessed)
 *    * redirectToFeed(false): whether or not to redirect to the feed after signing in (needs `redirects` to be true)
 *    * relogIfNecessary(true):  if there's a valid session or privateId, log out from that first.
 *
 * @param credentials either {email, password} or {privateId}
 * @returns {Function}
 */
export function accountLogin(credentials, options) {
    const options_ = Object.assign(
        { // defaults
            fetchData: true,
            doRedirects: true,
            redirectToFeed: false,
            relogIfNecessary: true, // if there's a valid session or privateId, log out from that first.
        },
        options
    );
    return (dispatch, getState) => {
        const state = getState();

        const {email} = parseCredentials(credentials);

        const prevPrivateId = getIn(state, ['router', 'currentParams', 'privateId']);
        const prevEmail = state.getIn(['user', 'email']);

        const wasLoggedIn = state.get('initialLoadFinished') && (prevPrivateId || prevEmail);

        if(state.get('loginInProcessFor') === email || _loginInProcessFor === email) {
            console.info('Already logging in as ', email, '. Canceling redundant attempt.');
            return;
        }

        if(state.get('initialLoadFinished') && (
             credentials.privateId && credentials.privateId === prevPrivateId ||
             credentials.email && credentials.email === prevEmail
           )
        ) {
                console.info(
                    'Already logged into this account (' +
                    (credentials.privateId || credentials.email) +
                    '). Aborting second login attempt.');
                return;
        }


        const curriedDispatch = data => dispatch({
            type: actionTypes.login,
            payload: Immutable.fromJS(data).merge({email: email, loggedIn: true})
        });

        return Promise.resolve()
        .then(() => {
            _loginInProcessFor = email;
            return dispatch({
                type: actionTypes.loginStarted,
                payload: {email}
            })
        })
        .then(() => {
            if (wasLoggedIn) {
                return logout()
                .then(() => {
                    if (options_.doRedirects && getIn(state, ['router', 'currentParams', 'privateId'])) {
                        return stateGoCurrent({privateId: ""})(dispatch, getState);
                    }
                });
            }
        })
        .then(() => {
            if(options_.doRedirects && credentials.privateId) {
                return stateGoCurrent({privateId: credentials.privateId})(dispatch, getState);
            }
        })
        .then(() =>
            login(credentials)
        )
        .then(() =>
            curriedDispatch({})
        )
        .then(() => {
            if(!options_.doRedirects) {
                return;
            } else if (options_.redirectToFeed) {
                return dispatch(actionCreators.router__stateGoResetParams("feed"))
            } else {
                return checkAccessToCurrentRoute(dispatch, getState);
            }
        })
        .then(response => {
                if(options_.fetchData) {
                    return fetchOwnedData(email, curriedDispatch);
                } else {
                    return Immutable.Map(); // only need to fetch data for non-new accounts
                }
            }
        )
        .then(() =>
            curriedDispatch({loginFinished: true})
        )
        .then(() =>
        /**
         * TODO this action is part of the session-upgrade hack documented in:
         * https://github.com/researchstudio-sat/webofneeds/issues/381#issuecomment-172569377
         */
            dispatch(actionCreators.reconnect())
        )
        .catch(error => {
            console.error("accountLogin ErrorObject", error);
            return Promise.resolve()
                .then(() => {
                    if(wasLoggedIn) {
                        return dispatch({
                            type: actionTypes.logout,
                            payload: Immutable.fromJS({loggedIn: false})
                        })
                    }
                })
                .then(() => {
                    const loginError = credentials.privateId ?
                        'invalid privateId' :
                        'unknown username/password combination';

                    dispatch(actionCreators.loginFailed({
                        loginError,
                        error,
{'fraction_non_alphanumeric': 0.11957142857142856, 'fraction_numerical': 0.003285714285714286, 'mean_word_length': 1.6919823110940204, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 36, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3318333', 'n_tokens_mistral': 3665, 'n_tokens_neox': 3529, 'n_words': 888}