package es.uv.saic.service;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import es.uv.saic.shared.domain.Usuari;
import es.uv.saic.shared.domain.UsuariRepository;
import es.uv.saic.shared.domain.UsuarisRol;
import es.uv.saic.shared.dto.TascaAsignadaDTO;

@Service
public class UsuariService {

	@Autowired
	private UsuariRepository usuariRepository;
	@Autowired
	private UsuarisRolService usuarisRolService;
	
	public List<Usuari> findAll() {
		return this.usuariRepository.findAll();
	}
	
	public Usuari findByUsername(String usuari) {
		return this.usuariRepository.findByUsername(usuari);
	}
	
	public boolean hasActiveRol(Usuari usuari) {
		return this.usuarisRolService.hasActiveRol(usuari);
	}
	
	public List<TascaAsignadaDTO> getActiveInstanciaTasques(Usuari usuari){
		return this.usuariRepository.findActiveInstanciaTasques(usuari.getUsuari());
	}
	
	public List<BigInteger> getActiveInstancies(Usuari usuari){
		
		if(usuari.isGranted() || usuarisRolService.findActiveRols(usuari).stream().anyMatch(r -> "adeit".equals(r.getRol().getNomRol()))) {
			return this.usuariRepository.findActiveInstanciesGranted(usuari.getUsuari());
		}
		else{
			return this.usuariRepository.findActiveInstancies(usuari.getUsuari());
		}
	}
	
	public List<BigInteger> getSupervisableProcessos(List<UsuarisRol> usuarisRols){
		List<BigInteger> a = new ArrayList<BigInteger>();
		for(UsuarisRol urol : usuarisRols) {
			if(urol.getRol().getNomRol().equals("c_resp")) {  // Responsable de centro
				a.addAll(this.usuariRepository.findSupervisableProcessosResp(urol.getOrgan().getId().getLugar()));
			}
			else if(urol.getRol().getNomRol().equals("c_supe")) { // Supervisor de centro
				a.addAll(this.usuariRepository.findSupervisableProcessosResp(urol.getOrgan().getId().getLugar()));
			}
			else if(urol.getRol().getNomRol().equals("e_supe")) { // Supervisor externo
				a.addAll(this.usuariRepository.findSupervisableProcessosResp(urol.getOrgan().getId().getLugar()));
			}
			else if(this.usuarisRolService.hasAssociatedProcs(urol.getRol().getNomRol())) { // Roles especiales (asociados a proceso)
				a.addAll(this.usuariRepository.findSupervisableProcessosSupervisor(this.usuarisRolService.findAssociatedProcs(urol.getRol().getNomRol())));
			}
			else { // Cualquier otro rol
				a.addAll(this.usuariRepository.findSupervisableProcessos(urol.getOrgan().getId().getLugar(), urol.getOrgan().getId().getTlugar()));
			}
		}
		
		return a.stream()
				 .distinct()
				 .collect(Collectors.toList());
	}
	
	public List<Integer> getSupervisableCentres(Usuari usuari){	
		List<Integer> a = new ArrayList<Integer>();
		for(UsuarisRol urol : usuarisRolService.findActiveRols(usuari)) {
			if(this.usuarisRolService.hasAssociatedProcs(urol.getRol().getNomRol())) { // special roles
				a.addAll(this.usuariRepository.findSupervisableCentresSupervisor(this.usuarisRolService.findAssociatedProcs(urol.getRol().getNomRol())));
			}
			else {
				a.addAll(this.usuariRepository.findSupervisableCentres(usuari.getUsuari()));
			}
		}
		
		return a.stream()
				 .distinct()
				 .collect(Collectors.toList());
	}
	
	public List<Usuari> getInstanceAsignedUsers(BigInteger idInstancia){
		return this.usuariRepository.getInstanceAsignedUsers(idInstancia);
	}
	
	public List<Usuari> findByRolCentre(Integer idRol, List<Integer> centres){
		return this.usuariRepository.findByRolCentre(idRol, centres);
	}
	
	public void save(Usuari u) {
		this.usuariRepository.save(u);
		this.usuariRepository.flush();
	}
	
}