'use strict';

const linuxUser = require('linux-sys-user').promise();
const objValidate = require('../utils/object_validate');
const {promisify} = require('util');
const pam = require('authenticate-pam');
const authenticate = promisify(pam.authenticate);

var User = {}

User.keyMap = {
	'username': {isRequired: true, type: 'string', min: 3, max: 500},
	'password': {isRequired: true, type: 'string', min: 3, max: 500},
}

User.backing = "PAM";

User.list = async function(){
	try{
		let users = await linuxUser.getUsers();

		for(let user of users){
			delete user.password
		}

		return users;
	}catch(error){
		throw error;
	}
};

User.get = async function(data){
	try{
		if(typeof data !== 'object'){
			let username = data;
			data = {};
			data.username = username;
		}
		
		let user = await linuxUser.getUserInfo(data.username);

		if(user){
			let obj = Object.create(this);
			Object.assign(obj, user);
			
			return obj;
		}else{
			let error = new Error('UserNotFound');
			error.name = 'UserNotFound';
			error.message = `PAM:${data.username} does not exists`;
			error.status = 404;
			throw error;
		}
	}catch(error){
		throw error;
	}
};

User.exists = async function(data){
	// Return true or false if the requested entry exists ignoring error's.
	try{
		await this.get(data);

		return true
	}catch(error){
		return false;
	}
};

User.create = async function(data) {
	try{
		data = objValidate.processKeys(this.keyMap, data);
		let systemUser = await linuxUser.addUser(data.username);
		await require('util').promisify(setTimeout)(500)
		let systemUserPassword = await linuxUser.setPassword(data.username, data.password);

		return this.get(data.username);

	}catch(error){
		if(error.message.includes('exists')){
			let error = new Error('UserNameUsed');
			error.name = 'UserNameUsed';
			error.message = `PAM:${data.username} already exists`;
			error.status = 409;

			throw error;
		}
		throw error;
	}
};

User.remove = async function(data){
	try{
		return await linuxUser.removeUser(this.username);
	}catch(error){
		throw error;
	}
};

User.setPassword = async function(data){
	try{
		await linuxUser.setPassword(this.username, data.password);

		return this;
	}catch(error){
		throw error;
	}
};

User.login = async function(data){
	try{
		let auth = await authenticate(data.username, data.password);
		let user = await User.get(data);

		return user;
	}catch(error){
		if (error == 'Authentication failure'){
			throw this.errors.login()
		}
		throw error;
	}
};

module.exports = {User};
