var util        = require('./util');
var bcrypt      = require('bcrypt-nodejs');

var unAuth      = { status: 'UNAUTHORIZED' };
var auth        = { status: 'AUTHORIZED' };
var error       = { status: 'ERROR' };

var mongoose    = require('mongoose');
var schemas     = {};
var models      = {};

var online      = {};
var db;

schemas.account = new mongoose.Schema({ email: { type: String, unique: true}, name: { type: String, unique: true}, password_hash: String, password_salt: String });
models.Account = mongoose.model('Account', schemas.account);

function init(link, callback) {
    util.log('Connecting to database ..');
    mongoose.connect(link, { server: { socketOptions: { connectTimeoutMS: 5000 }}});
    db = mongoose.connection;

    db.on('error', function (err) {
        util.log(err.message);
        callback(err);
    });

    db.once('open', function () {
        util.log('Connected to DB');
        models.Account.count({}, function(err, count) {
            util.log('Registered accounts: ' + count);
            callback();
        });
    });
}

function status(sessionId) {
    // USE SESSION ID ONLY, NOT THE WHOLE COOKIE
    var sess = online[sessionId];

    if (sess) {
        return sess;
    } else {
        online[sessionId] = util.conjure('AUTH', unAuth);
        return online[sessionId];
    }
}

function onlineCount() {
    return util.count(online);
}

function getAccount(email) {
    return models.Account.findOne({ email: email }).exec();
}

function saveAccount(data) {
    return models.Account.create(data);
}

function logout(sessionId, callback) {
    util.log('LOGOUT: ' + online[sessionId].email);
    delete online[sessionId];
    callback(util.conjure('LOGOUT', unAuth));
}

function login(sessionId, data, callback) {
    var email       = data.email;
    var password    = data.password;
    var valid;

    getAccount(email).then(function (account) {
        if (account) {
            valid = bcrypt.compareSync(account.password_salt + data.password, account.password_hash);

            if (valid) {
                util.log('LOGIN: ' + email + ' SUCCESS');
                online[sessionId] = util.conjure('LOGIN', auth);
                online[sessionId].email = account.email;
                callback(util.conjure('LOGIN', auth));
            } else {
                util.log('LOGIN: ' + email + ' ERROR');
                callback(util.conjure('LOGIN', unAuth));
            }

        } else {
            util.log('LOGIN: ' + email + ' ERROR');
            callback(util.conjure('LOGIN', unAuth));
        }
    });
}

function register(sessionId, data, callback) {
    var password_salt;
    var password_hash;

    if (!util.validateEmail(data.email) || !util.validatePassword(data.password, data.passwordConfirmation)) {
        util.log('REGISTRATION_VALIDATION_ERROR: ' + data.email);
        callback(util.conjure('REGISTER', error)); // DO BETTER VALIDATION
        return null;
    }

    password_salt = util.getRandomHash();
    password_hash = bcrypt.hashSync(password_salt + data.password, null);

    saveAccount({ email: data.email, name: data.name, password_salt: password_salt, password_hash: password_hash }).then(function (account) {
        util.log('REGISTRATION_OK: ' + data.email + ' ' + data.name);
        callback(util.conjure('REGISTER', { status: 'OK' }));
    }, function (err) {
        util.log('REGISTRATION_ERROR: ' + data.email + ' ' + data.name);
        callback(util.conjure('REGISTER', error));
    });
}

module.exports = {
    init:           init,
    status:         status,
    onlineCount:    onlineCount,
    login:          login,
    logout:         logout,
    register:       register
}
