package net.eclettica.esecure.dao;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import net.eclettica.esecure.conf.AuthConfig;
import net.eclettica.esecure.manager.EsAccountManager;
import net.eclettica.esecure.models.EsAccount;
import net.eclettica.esecure.models.EsAuth;
import net.eclettica.esecure.models.EsRole;

public class EsDao implements EsAccountManager {

	@Override
	public String findByLogin(String username, String password) {
		if (username == null || username.trim().isEmpty())
			return null;
		models.eSecurePlay1.EsAccount res = models.eSecurePlay1.EsAccount
				.find("username =:username and password=:password").setParameter("username", username)
				.setParameter("password", password).first();
		if (res == null) {
			return null;
		}
		return res.getUuid();
	}

	@Override
	public String findByLogin(String username) {
		if (username == null || username.trim().isEmpty())
			return null;
		models.eSecurePlay1.EsAccount res = models.eSecurePlay1.EsAccount.find("username = :username").setParameter("username", username).first();
		if (res == null) {
			return null;
		}
		return res.getUuid();
	}

	public void changePassword(String uuid, String psw) {
		if (psw == null || uuid == null)
			return;
		models.eSecurePlay1.EsAccount user = models.eSecurePlay1.EsAccount.find("uuid = :uuid").setParameter("uuid", uuid).first();
		user.setPassword(cryptPassword(psw));
		user.save();

	}
	
	@Override
	public EsAccount findAccountById(String uuid) {
		models.eSecurePlay1.EsAccount res = models.eSecurePlay1.EsAccount.find("uuid = ? ", uuid).first();

		return res;

	}

	@Override
	public List<EsAuth> findAuthByRole(String roleUuid) {
		List<EsAuth> la;
		models.eSecurePlay1.EsRole role = models.eSecurePlay1.EsRole.find("name = ?", roleUuid).first();
		if (role != null) {
			la = new ArrayList<EsAuth>();
			for (models.eSecurePlay1.EsAuth auth : role.getAuths()) {
				la.add(auth);
			}
			return la;
		}
		return null;

	}

	@Override
	public List<EsAccount> findUserByRole(String roleName) {
		List<EsAccount> lu;
		models.eSecurePlay1.EsRole rl = models.eSecurePlay1.EsRole.find("name = ?", roleName).first();
		if (rl == null)
			return null;

		lu = new ArrayList<EsAccount>();
		for (models.eSecurePlay1.EsAccount us : rl.getUsers()) {
			lu.add(us);
		}
		return lu;

	}

	@Override
	public EsRole findRole(String roleName) {
		models.eSecurePlay1.EsRole res = models.eSecurePlay1.EsRole.find("name = ?", roleName).first();
		return res;
	}

	@Override
	public List<EsRole> findRoleByAuth(String authUuid) {
		List<EsRole> lr;
		models.eSecurePlay1.EsAuth auth = models.eSecurePlay1.EsAuth.find("uuid =?", authUuid).first();

		if (auth != null) {
			lr = new ArrayList<EsRole>();
			for (models.eSecurePlay1.EsRole rl : auth.getRoles()) {
				lr.add(rl);
			}
			return lr;
		}
		return null;

	}

	@Override
	public List<EsRole> findRoleByUser(String uuid) {
		List<EsRole> lr;
		models.eSecurePlay1.EsAccount acc = models.eSecurePlay1.EsAccount.find("uuid =?", uuid).first();

		if (acc != null) {
			lr = new ArrayList<EsRole>();
			for (models.eSecurePlay1.EsRole rl : acc.getRoles()) {
				lr.add(rl);
			}
			return lr;
		}
		return null;

	}

	@Override
	public List<EsAccount> findAllUser() {
		List<EsAccount> lr = models.eSecurePlay1.EsAccount.find("").fetch();
		return lr;
	}

	@Override
	public List<EsRole> findAllRole() {
		List<EsRole> lr = models.eSecurePlay1.EsRole.find("").fetch();
		return lr;
	}

	@Override
	public List<EsAuth> findAllAuth() {
		List<EsAuth> lr = models.eSecurePlay1.EsAuth.find("").fetch();
		return lr;
	}

	@Override
	public void editAuth(String authUuid, String nome, String descrizione) {

		models.eSecurePlay1.EsAuth au = models.eSecurePlay1.EsAuth.find("uuid = ?", authUuid).first();
		au.setName(nome);
		au.setDescription(descrizione);

		au.save();

	}

	@Override
	public void createAuth(String nome, String descrizione) {
		models.eSecurePlay1.EsAuth au = new models.eSecurePlay1.EsAuth();
		au.setName(nome);
		au.setDescription(descrizione);
		au.create();
	}

	@Override
	public void editRole(String roleUuid, String nome, String descrizione) {
		models.eSecurePlay1.EsRole rl = models.eSecurePlay1.EsRole.find("uuid = ?", roleUuid).first();
		if (rl == null)
			return;
		rl.setName(nome);
		rl.setDescription(descrizione);
		rl.save();

	}

	@Override
	public void createRole(String nome, String descrizione) {
		models.eSecurePlay1.EsRole rl = new models.eSecurePlay1.EsRole();
		rl.setName(nome);
		rl.setDescription(descrizione);
		rl.create();
	}

	public void editUser(String uuid, String username, String group) {
		models.eSecurePlay1.EsAccount user = models.eSecurePlay1.EsAccount.find("uuid = ?", uuid).first();
		if (user == null)
			return;

		user.setUsername(username);
		user.setUserGroup(group);
		user.save();

	}

	@Override
	public String createNewUser(String username, String psw, String group) {
		models.eSecurePlay1.EsAccount us = new models.eSecurePlay1.EsAccount();
		us.setUsername(username);
		us.setPassword(psw);
		us.setUserGroup(group);
		us.create();
		String uuid = us.getUuid();

		return uuid;
	}

	@Override
	public void deleteRole(String roleUuid) {
		models.eSecurePlay1.EsRole rl = models.eSecurePlay1.EsRole.find("name = ?", roleUuid).first();
		rl.delete();

	}

	@Override
	public void deleteU(String uuid) {
		models.eSecurePlay1.EsAccount user = models.eSecurePlay1.EsAccount.find("uuid = ?", uuid).first();
		user.delete();

	}

	public String cryptPassword(String clearTextPassword) {
		MessageDigest md;
		StringBuffer sb = new StringBuffer();
		try {
			md = MessageDigest.getInstance("MD5");

			byte[] messDig5 = md.digest(clearTextPassword.getBytes());
			for (int i = 0; i < messDig5.length; i++) {
				String tmpStr = "0" + Integer.toHexString((0xff & messDig5[i]));
				sb.append(tmpStr.substring(tmpStr.length() - 2));
			}

		} catch (NoSuchAlgorithmException e) {

			e.printStackTrace();
		}
		return sb.toString();
	}

	@Override
	public void clearRolesForUser(String uuid) {
		models.eSecurePlay1.EsAccount user = models.eSecurePlay1.EsAccount.find("uuid = ?", uuid).first();
		if (user == null || user.getRoles().isEmpty())
			return;

		Set<models.eSecurePlay1.EsRole> oldRoles = new HashSet<models.eSecurePlay1.EsRole>();

		for (models.eSecurePlay1.EsRole rl : user.getRoles()) {
			oldRoles.add(rl);
		}
		for (models.eSecurePlay1.EsRole r : oldRoles) {
			r.getUsers().remove(user);

			r.save();
			user.getRoles().remove(r);
		}

		user.save();
	}

	@Override
	public void clearRolesForAuth(EsAuth au) {
		models.eSecurePlay1.EsAuth a = (models.eSecurePlay1.EsAuth) au;
		if (a.getRoles().isEmpty())
			return;

		Set<models.eSecurePlay1.EsRole> oldRoles = new HashSet<models.eSecurePlay1.EsRole>();
		for (models.eSecurePlay1.EsRole rl : a.getRoles()) {
			oldRoles.add(rl);
		}

		for (models.eSecurePlay1.EsRole r : oldRoles) {
			r.getAuths().remove(r);
			r.save();
			a.getRoles().remove(r);
		}

		a.save();
	}

	@Override
	public void clearAuthsForRole(EsRole rl) {
		models.eSecurePlay1.EsRole r = (models.eSecurePlay1.EsRole) rl;
		if (r.getAuths().isEmpty())
			return;

		Set<models.eSecurePlay1.EsAuth> oldAuths = new HashSet<models.eSecurePlay1.EsAuth>();
		for (models.eSecurePlay1.EsAuth au : r.getAuths()) {
			oldAuths.add(au);
		}

		for (models.eSecurePlay1.EsAuth a : oldAuths) {

			a.getRoles().remove(r);

			a.save();

			r.getAuths().remove(a);
		}

		r.save();

	}

	@Override
	public boolean validate(String username, String psw, String group) {

		if (username != null && psw != null && group != null
				&& psw.length() > AuthConfig.getInstance().getMinPassword()) {
			return true;
		}
		return false;

	}

	@Override
	public boolean validateEdit(String username, String group) {

		if (username != null && group != null) {
			return true;
		}

		return false;

	}

	@Override
	public EsAuth cercaAuth(String name) {

		EsAuth auth = findAuthByName(name);

		return auth;

	}

	@Override
	public EsAuth findAuthByName(String name) {
		models.eSecurePlay1.EsAuth res = models.eSecurePlay1.EsAuth.find("name = ?", name).first();
		return res;
	}

	public void rimuoviEsRuoloDaUser(EsAccount us, EsRole rl) {

		models.eSecurePlay1.EsRole r = (models.eSecurePlay1.EsRole) rl;
		models.eSecurePlay1.EsAccount u = (models.eSecurePlay1.EsAccount) us;
		u.getRoles().remove(r);

	}

	public void rimuoviEsRuoloDaAuth(EsAuth a, EsRole rl) {
		models.eSecurePlay1.EsRole r = (models.eSecurePlay1.EsRole) rl;
		models.eSecurePlay1.EsAuth au = (models.eSecurePlay1.EsAuth) a;
		au.getRoles().remove(r);

	}

	public void addUserRole(String uuid, String role) {

		models.eSecurePlay1.EsAccount u = models.eSecurePlay1.EsAccount.find("uuid = ?", uuid).first();
		models.eSecurePlay1.EsRole rl = models.eSecurePlay1.EsRole.find("name = ?", role).first();
		u.getRoles().add(rl);

		u.save();
	}

	public void addAuthRoles(EsAuth au, EsRole r) {

		models.eSecurePlay1.EsAuth a = (models.eSecurePlay1.EsAuth) au;
		models.eSecurePlay1.EsRole rl = (models.eSecurePlay1.EsRole) r;
		a.getRoles().add(rl);
		a.save();
	}

	public void addRoleAuths(EsAuth au, EsRole r) {

		models.eSecurePlay1.EsAuth a = (models.eSecurePlay1.EsAuth) au;
		models.eSecurePlay1.EsRole rl = (models.eSecurePlay1.EsRole) r;
		rl.getAuths().add(a);
		rl.save();
	}

	public Set<EsRole> listaRuoliUser(String uuid) {
		models.eSecurePlay1.EsAccount u = models.eSecurePlay1.EsAccount.find("uuid = ?", uuid).first();
		Set<EsRole> ruoli = new HashSet<EsRole>();
		for (EsRole ruolo : u.getRoles()) {
			ruoli.add(ruolo);
		}
		return ruoli;
	}

	public Set<EsRole> listaRuoliAuth(EsAuth au) {
		models.eSecurePlay1.EsAuth a = (models.eSecurePlay1.EsAuth) au;
		Set<EsRole> ruoli = new HashSet<EsRole>();
		for (EsRole ruolo : a.getRoles()) {
			ruoli.add(ruolo);
		}
		return ruoli;
	}

	public Set<EsAuth> listaAuthsRole(EsRole rl) {
		models.eSecurePlay1.EsRole r = (models.eSecurePlay1.EsRole) rl;

		Set<EsAuth> autoriz = new HashSet<EsAuth>();

		for (EsAuth auth : r.getAuths()) {
			autoriz.add(auth);
		}
		return autoriz;
	}

	@Override
	public void deleteA(String auth) {
		models.eSecurePlay1.EsAuth au = models.eSecurePlay1.EsAuth.find("name = ?", auth).first();
		au.delete();

	}

	

	public boolean verifyPassword(String uuid, String psw) {
		models.eSecurePlay1.EsAccount user = models.eSecurePlay1.EsAccount.find("uuid = ?", uuid).first();
		String oldpsw = user.getPassword();
		if (psw.equals(oldpsw)) {
			return true;
		}
		return false;
	}

	public void saveA(EsAuth a) {
		models.eSecurePlay1.EsAuth au = (models.eSecurePlay1.EsAuth) a;
		au.save();
	}

	public void saveU(EsAccount u) {
		models.eSecurePlay1.EsAccount user = (models.eSecurePlay1.EsAccount) u;
		user.save();
	}

	@Override
	public boolean existsUser(String uuid) {
		models.eSecurePlay1.EsAccount user = models.eSecurePlay1.EsAccount.find("uuid = ?", uuid).first();
		if (user != null) {
			return true;
		}
		return false;
	}

	@Override
	public String findByUsername(String username) {
		models.eSecurePlay1.EsAccount res = models.eSecurePlay1.EsAccount.find("username = ?", username).first();
		if (res != null) {
			return res.getUuid();
		}
		return null;
	}

	@Override
	public void addUserRoles(String uuid, String[] roles) {
		models.eSecurePlay1.EsAccount u = models.eSecurePlay1.EsAccount.find("uuid = ?", uuid).first();
		for (String r : roles) {
			models.eSecurePlay1.EsRole rl = models.eSecurePlay1.EsRole.find("name = ?", r).first();
			u.getRoles().add(rl);
			u.save();
		}

	}
}
