/**
 * The main authentication module
 */

'use strict';

const passport = require('passport'),
    LocalStrategy = require('passport-local').Strategy,
    SamlStrategy = require('passport-saml').Strategy,
    FacebookStrategy = require('passport-facebook').Strategy,
    GoogleStrategy = require('passport-google-oauth').OAuth2Strategy,
    accounts = require('../controllers/AccountController'),
    authProviders = config.get("authenticationProviders"),
    authConfig = config.get("authentication");
    logger = require('../utils/Logger').loggers.get('auth');
/**
 * User serialization
 */
passport.serializeUser(function (user, done) {
    done(null, user);
});

passport.deserializeUser(function (user, done) {
    done(null, user);
});

/**
 * Local authentication
 */
if (!authConfig || !authConfig.disableLocalLogin) {
    passport.use(new LocalStrategy({
            usernameField: 'email',
            passwordField: 'pass'
        },
        function (username, password, done) {
            accounts.doLocalLogin(username, password).then(result => {
                return done(null, result);
            }).catch(err => {
                return done(err);
            });
        }
    ));
}

/**
 * SAML authentication
 */
if (authProviders && authProviders.saml) {
    passport.use(new SamlStrategy(
        {
            entryPoint: authProviders.saml.entryPoint,
            cert: authProviders.saml.cert
        },
        function (profile, done) {
            // nameID should be configured in provider as email
            const email = profile.nameID;
            if (!email) {
                return done(new Error("No email found from SSO provider."), null);
            } else {
                accounts.doEmailLogin(email, function (err, user) {
                    return done(err, user);
                });
            }
        },
        function(err) {
            logger.info(err);
        }
    ));
}

if (authProviders && authProviders.facebook) {
    passport.use(new FacebookStrategy({
        clientID: authProviders.facebook.clientId,
        clientSecret: authProviders.facebook.secret,
        callbackURL: authProviders.facebook.callbackURL,
        profileFields: ['id', 'displayName', 'name', 'emails']
    },
        function (accessToken, refreshToken, profile, done) {
            if (profile && profile.emails) {
                let email = profile.emails[0].value; // emails [{value, verified}]
                accounts.doEmailLogin(email, function (err, user) {
                    return done(err, user);
                });
            } else {
                return done(new Error("No email address found after facebook login."
                  + " Please contact administrator."), null);
            }
        }
    ));
}

if (authProviders && authProviders.google) {
    passport.use(new GoogleStrategy({
        clientID: authProviders.google.clientId,
        clientSecret: authProviders.google.secret,
        callbackURL: authProviders.google.callbackURL,
        scope: ['profile', 'email']
    },
        function (accessToken, refreshToken, profile, done) {
            if (profile && profile.emails) {
                let email = profile.emails[0].value; // emails [{value, verified}]
                accounts.doEmailLogin(email, function (err, user) {
                    return done(err, user);
                });
            } else {
                return done(new Error("No email address found after google login."
                    + " Please contact administrator."), null);
            }
        }
    ));
}


/**
 * Authentication object
 * @type {{passport: (*|exports), authProvider: authProvider, initialize: initialize, session: session}}
 */
var Authentication = {
    passport: passport,
    authProvider: function(providerName) {
        return passport.authenticate(providerName);
    },
    initialize: function() {
        return passport.initialize();
    },
    session: function() {
        return passport.session();
    }
};
module.exports = Authentication;
