package es.uv.saic.web;

import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import es.uv.saic.domain.Acreditacio;
import es.uv.saic.domain.AcreditacioTransfer;
import es.uv.saic.domain.DummyDataTransfer;
import es.uv.saic.domain.Email;
import es.uv.saic.domain.EvidenciaIndicadorEnquesta;
import es.uv.saic.domain.EvidenciaIndicadorEnquestaPK;
import es.uv.saic.domain.Instancia;
import es.uv.saic.domain.InstanciaTasca;
import es.uv.saic.domain.Organ;
import es.uv.saic.domain.Plantilla;
import es.uv.saic.domain.Proces;
import es.uv.saic.domain.Rol;
import es.uv.saic.domain.Tasca;
import es.uv.saic.domain.Usuari;
import es.uv.saic.domain.UsuarisRol;
import es.uv.saic.dto.TemplateDataDTO;
import es.uv.saic.feign.PlantillaClient;
import es.uv.saic.service.AcreditacioService;
import es.uv.saic.service.EmailService;
import es.uv.saic.service.EvidenciaIndicadorEnquestaService;
import es.uv.saic.service.IndicadorEnquestaService;
import es.uv.saic.service.InstanciaService;
import es.uv.saic.service.InstanciaTascaService;
import es.uv.saic.service.InstanciaTascaVerService;
import es.uv.saic.service.OrganService;
import es.uv.saic.service.ProcesService;
import es.uv.saic.service.RolService;
import es.uv.saic.service.TascaService;
import es.uv.saic.service.TipusService;
import es.uv.saic.service.UsuariService;
import es.uv.saic.service.UsuarisRolService;

@Controller
public class AdminController {

	@Autowired
	private OrganService os;
	@Autowired
	private ProcesService ps;
	@Autowired
	private InstanciaService is;
	@Autowired
	private InstanciaTascaService its;
	@Autowired
	private InstanciaTascaVerService itsver;
	@Autowired
	private UsuariService us;
	@Autowired
	private RolService rs;
	@Autowired
	private UsuarisRolService urs;
	@Autowired
	private TascaService ts;
	@Autowired
	private TipusService tps;
	@Autowired
	private EmailService es;
	@Autowired
	private IndicadorEnquestaService ies;
	@Autowired
	private EvidenciaIndicadorEnquestaService eies;
	@Autowired
	private PlantillaClient plc;
	@Autowired
	private AcreditacioService as;
	@Value("${saic.data.filePath}")
	private String filePath;
	@Value("${saic.data.templates.filePath}")
	private String templatePath;
	
	public static final String DDMMYYYY = "dd/MM/yyyy";
	
	// GET para conseguir todas las instancias del sistema en ese momento.
	@GetMapping("/admin/instances")
	@Secured({"ROLE_ADMIN"})
	public String getInstances(Model model, Authentication auth) {		
		this.loadInstanceData(model);
		return "adminInstances";
	}
	 
	// Función utilizada para conseguir las instancias que tiene todo el sistema
	public void loadInstanceData(Model model) {
		List<DummyDataTransfer> centres = new ArrayList<DummyDataTransfer>();
		List<DummyDataTransfer> titulacions = new ArrayList<DummyDataTransfer>();
		List<DummyDataTransfer> procediments = new ArrayList<DummyDataTransfer>();
		
		for(Organ o : os.getCentres()) {
			DummyDataTransfer a = new DummyDataTransfer();
			a.setText(o.getNomCas());
			a.setText2(o.getNomVal());
			a.setValue(o.getId().getLugar());
			centres.add(a);
		}
		for(Proces p : ps.getAll()) {
			DummyDataTransfer a = new DummyDataTransfer();
			a.setText(p.getNomProces()); 
			a.setText2("(" + p.getIdProces() + " - Ver. "+ p.getVersio() +") " + p.getNomProces() + " " + p.getTitolCas());
			a.setText3("(" + p.getIdProces() + " - Ver. "+ p.getVersio() +") " + p.getNomProces() + " " + p.getTitolVal());
			a.setValue(p.getIdProces());
			procediments.add(a);
		}
		
		model.addAttribute("centers", centres);
		model.addAttribute("titulations", titulacions);
		model.addAttribute("procedures", procediments);
	}
	
	// POST que recoge los campos introducidos en los inputs (Proceso, centro y titulación) y busca las instancias relacionadas
	@PostMapping("/admin/instances")
	@Secured({"ROLE_ADMIN"})
	public String instantiate(Model model, Authentication auth, 
			@RequestParam("procedure") Integer idProces,
			@RequestParam("center") Integer idCentre,
			@RequestParam("titulation") Integer idTitulacio,
			HttpSession session) {
		
		Proces p = ps.findByID(idProces);
		List<String> errorCas = new ArrayList<String>();
		List<String> errorVal = new ArrayList<String>();
		List<String> successCas = new ArrayList<String>();
		List<String> successVal = new ArrayList<String>();
		
		if(p.getAmbit().equals("U")) { // Type U procedure
			Organ centre = os.findByID("C", idCentre);
			BigInteger idInstancia = is.instantiateU(idProces, idTitulacio);
			if(!idInstancia.equals(BigInteger.valueOf(0))) {
				InstanciaTasca activa = its.findActiveByInstancia(idInstancia);
				for(Usuari u : us.getInstanceAsignedUsers(idInstancia)) {
					Email email = new Email();
					email.setUsusari(u);
					email.setInstanciaTasca(activa);
					es.addEmail(email);
				}
				successCas.add("Procediment: "+p.getNomProces()+", Centre: "+centre.getNomCas());
				successVal.add("Procediment: "+p.getNomProces()+", Centre: "+centre.getNomVal());
				model.addAttribute("success", true);
			}
			else {
				errorCas.add("Procediment: "+p.getNomProces()+", Centre: "+centre.getNomCas());
				errorVal.add("Procediment: "+p.getNomProces()+", Centre: "+centre.getNomVal());
				model.addAttribute("error", true);
			}
		}
		else if(idTitulacio > 2 && p.getAmbit().equals("T")) { // Type T procedure for one place
			Organ o = os.findByID("T", idTitulacio);
			BigInteger idInstancia = is.instantiateT(idProces, idTitulacio);
			if(!idInstancia.equals(BigInteger.valueOf(0))) {
				InstanciaTasca activa = its.findActiveByInstancia(idInstancia);
				for(Usuari u : us.getInstanceAsignedUsers(idInstancia)) {
					Email email = new Email();
					email.setUsusari(u);
					email.setInstanciaTasca(activa);
					es.addEmail(email);
				}
				successCas.add("Procediment: "+p.getNomProces()+", Centre: "+o.getOrgan().getNomCas()+", Titulació: "+o.getNomCas());
				successVal.add("Procediment: "+p.getNomProces()+", Centre: "+o.getOrgan().getNomVal()+", Titulació: "+o.getNomVal());
				model.addAttribute("success", true);
			}
			else {
				errorCas.add("Procediment: "+p.getNomProces()+", Centre: "+o.getOrgan().getNomCas()+", Titulació: "+o.getNomCas());
				errorVal.add("Procediment: "+p.getNomProces()+", Centre: "+o.getOrgan().getNomVal()+", Titulació: "+o.getNomVal());
				model.addAttribute("error", true);
			}
		}
		else if(idTitulacio <= 2 && p.getAmbit().equals("T")){
			List<Organ> titulacions;
			if(idTitulacio == 0) {  // Type T procedure for all active places
				titulacions = os.getTitulacionsByCentre(idCentre);
			}
			else {  // Type T procedure for one whole category place (masters/grados)
				titulacions = os.getTitulacionsByTypeCentre(idCentre, idTitulacio);
			}
			for(Organ o : titulacions) {
				BigInteger idInstancia = is.instantiateT(idProces, o.getId().getLugar());
				if(!idInstancia.equals(BigInteger.valueOf(0))) {
					InstanciaTasca activa = its.findActiveByInstancia(idInstancia);
					for(Usuari u : us.getInstanceAsignedUsers(idInstancia)) {
						Email email = new Email();
						email.setUsusari(u);
						email.setInstanciaTasca(activa);
						es.addEmail(email);
					}
					successCas.add("Procediment: "+p.getNomProces()+", Centre: "+o.getOrgan().getNomCas()+", Titulació: "+o.getNomCas());
					successVal.add("Procediment: "+p.getNomProces()+", Centre: "+o.getOrgan().getNomVal()+", Titulació: "+o.getNomVal());
				}
				else {
					errorCas.add("Procediment: "+p.getNomProces()+", Centre: "+o.getOrgan().getNomCas()+", Titulació: "+o.getNomCas());
					errorVal.add("Procediment: "+p.getNomProces()+", Centre: "+o.getOrgan().getNomVal()+", Titulació: "+o.getNomVal());
				}
			}
		}
		else if(p.getAmbit().equals("C")) {
			if(idCentre == 0) { // Type C procedure for all active places
				for(Organ centre : os.getActiveCentres()) {
					Organ titulacio = os.findByID("T", idTitulacio);
					BigInteger idInstancia = is.instantiateC(idProces, centre.getId().getLugar(), idTitulacio);
					if(!idInstancia.equals(BigInteger.valueOf(0))) {
						InstanciaTasca activa = its.findActiveByInstancia(idInstancia);
						for(Usuari u : us.getInstanceAsignedUsers(idInstancia)) {
							Email email = new Email();
							email.setUsusari(u);
							email.setInstanciaTasca(activa);
							es.addEmail(email);
						}
						successCas.add("Procediment: "+p.getNomProces()+", Centre: "+centre.getNomCas()+", Titulació: "+titulacio.getNomCas());
						successVal.add("Procediment: "+p.getNomProces()+", Centre: "+centre.getNomVal()+", Titulació: "+titulacio.getNomVal());
						model.addAttribute("success", true);
					}
					else {
						errorCas.add("Procediment: "+p.getNomProces()+", Centre: "+centre.getNomCas()+", Titulació: "+titulacio.getNomCas());
						errorVal.add("Procediment: "+p.getNomProces()+", Centre: "+centre.getNomVal()+", Titulació: "+titulacio.getNomVal());
						model.addAttribute("error", true);
					}
				}	
			}
			else if(idCentre > 0) { // Type C procedure for one place
				Organ titulacio = os.findByID("T", idTitulacio);
				Organ centre = os.findByID("C", idCentre);
				BigInteger idInstancia = is.instantiateC(idProces, idCentre, idTitulacio);
				if(!idInstancia.equals(BigInteger.valueOf(0))) {
					InstanciaTasca activa = its.findActiveByInstancia(idInstancia);
					for(Usuari u : us.getInstanceAsignedUsers(idInstancia)) {
						Email email = new Email();
						email.setUsusari(u);
						email.setInstanciaTasca(activa);
						es.addEmail(email);
					}
					successCas.add("Procediment: "+p.getNomProces()+", Centre: "+centre.getNomCas()+", Titulació: "+titulacio.getNomCas());
					successVal.add("Procediment: "+p.getNomProces()+", Centre: "+centre.getNomVal()+", Titulació: "+titulacio.getNomVal());
					model.addAttribute("success", true);
				}
				else {
					errorCas.add("Procediment: "+p.getNomProces()+", Centre: "+centre.getNomCas()+", Titulació: "+titulacio.getNomCas());
					errorVal.add("Procediment: "+p.getNomProces()+", Centre: "+centre.getNomVal()+", Titulació: "+titulacio.getNomVal());
					model.addAttribute("error", true);
				}
			}
		}
		
		model.addAttribute("successCas", successCas);
		model.addAttribute("successVal", successVal);
		model.addAttribute("errorCas", errorCas);
		model.addAttribute("errorVal", errorVal);
		if(errorCas.isEmpty()) {
			model.addAttribute("error", true);
		}
		if(successCas.isEmpty()) {
			model.addAttribute("success", true);
		}
		this.loadInstanceData(model);
		
		return "adminInstances";
	}

	// GET que recoge todos los procedimientos del sistema
	@GetMapping("/admin/procedures")
	@Secured({"ROLE_ADMIN"})
	public String getProcedures(Model model, Authentication auth) {
		this.loadProceduresData(model);
		return "adminProcedures";
	}
	
	// Función utilizada en el GET que recoge todos los procedimientos
	public void loadProceduresData(Model model) {
		List<DummyDataTransfer> procediments = new ArrayList<DummyDataTransfer>();
		for(Proces p : ps.getAll()) {
			DummyDataTransfer a = new DummyDataTransfer();
			a.setText(p.getNomProces());
			a.setText2("(" + p.getIdProces() + " - Ver. "+ p.getVersio() +") " + p.getNomProces() + " " + p.getTitolCas());
			a.setText3("(" + p.getIdProces() + " - Ver. "+ p.getVersio() +") " + p.getNomProces() + " " + p.getTitolVal());
			a.setValue(p.getIdProces());
			procediments.add(a);
		}
		model.addAttribute("procedures", procediments);
	}
	
	// POST que elimina una instancia concreta
	@PostMapping("/admin/instance/delete")
	@Secured({"ROLE_ADMIN"})
	public void deleteInstance(Model model, Authentication auth, HttpServletResponse response, @RequestParam BigInteger idInstancia) throws IOException {

		Instancia instancia = is.findByID(idInstancia);
		List<InstanciaTasca> instanciaTasques = its.findByInstancia(instancia.getIdInstancia());
		for(InstanciaTasca instanciaTasca : instanciaTasques) {
			Files.deleteIfExists(Paths.get(this.filePath+instanciaTasca.getEvidencia()));
		}
		is.deleteInstance(instancia);
		
		response.sendRedirect("/supervision");
	}
	
	// POST que reinicia una instancia por completo
	@PostMapping("/admin/instance/clear")
	@Secured({"ROLE_ADMIN", "ROLE_MANAGER"})
	public void clearInstance(Model model, Authentication auth, HttpServletResponse response, @RequestParam BigInteger idInstancia) throws IOException {
		
		Instancia instancia = is.findByID(idInstancia);
		List<InstanciaTasca> instanciaTasques = its.findByInstancia(instancia.getIdInstancia());
		for(InstanciaTasca instanciaTasca : instanciaTasques) {
			Files.deleteIfExists(Paths.get(this.filePath+instanciaTasca.getEvidencia()));
		}
		is.clearInstance(instancia);
		instancia.setEstat("A");
		is.save(instancia);

		this.itsver.deleteByIdInstancia(idInstancia);
		
		InstanciaTasca activa = its.findActiveByInstancia(idInstancia);
		if(activa.getTasca().getRol().getNomRol().equals("sys")) {
			activa = this.its.system(activa);
		}
		
		for(Usuari u : us.getInstanceAsignedUsers(idInstancia)) {
			Email email = new Email();
			email.setUsusari(u);
			email.setInstanciaTasca(activa);
			es.addEmail(email);
		}
		
		response.sendRedirect("/procedure/"+instancia.getIdInstancia().toString());
	}
	
	// POST que establece que una instancia ha sido cerrada, cambiandole su estado
	@PostMapping("/admin/instance/close")
	@Secured({"ROLE_ADMIN", "ROLE_MANAGER"})
	public void closeInstance(Model model, Authentication auth, HttpServletResponse response, @RequestParam BigInteger idInstancia) throws IOException {
		
		Instancia instancia = is.findByID(idInstancia);
		instancia.setEstat("C");
		InstanciaTasca instanciaTasca = its.findActiveByInstancia(instancia.getIdInstancia());
		instanciaTasca.setEstat(null);
		its.save(instanciaTasca);
		is.save(instancia);
		
		response.sendRedirect("/procedure/"+instancia.getIdInstancia().toString());
	}
	
	// POST que se encarga de eliminar una tarea concreta de una instancia
	@PostMapping("/admin/instance/task/remove")
	@Secured({"ROLE_ADMIN", "ROLE_MANAGER"})
	public void removeTask(Model model, Authentication auth, HttpServletResponse response, @RequestParam BigInteger idInstanciaTasca) throws IOException {
		
		InstanciaTasca instanciaTasca = its.findById(idInstanciaTasca);
		Files.deleteIfExists(Paths.get(this.filePath+instanciaTasca.getEvidencia()));
		its.remove(instanciaTasca.getIdInstanciaTasca());
		response.sendRedirect("/procedure/"+instanciaTasca.getInstancia().getIdInstancia().toString());
	}
	
	// POST que se encarga de reiniciar por completo una tarea de una instancia
	@PostMapping("/admin/instance/task/clear")
	@Secured({"ROLE_ADMIN", "ROLE_MANAGER"})
	public void clearTask(Model model, Authentication auth, HttpServletResponse response, @RequestParam BigInteger idInstanciaTasca) throws IOException {
		
		InstanciaTasca instanciaTasca = its.findById(idInstanciaTasca);
		Files.deleteIfExists(Paths.get(this.filePath+instanciaTasca.getEvidencia()));
		instanciaTasca.setDataFet(null);
		instanciaTasca.setEvidencia(null);
		instanciaTasca.setUsuari(null);
		instanciaTasca.setEstat(null);
		instanciaTasca.setText(null);
		if(instanciaTasca.getTasca().getRol().getNomRol().equals("sys")) {
			instanciaTasca = this.its.system(instanciaTasca);
		}
		its.save(instanciaTasca);
		
		response.sendRedirect("/procedure/"+instanciaTasca.getInstancia().getIdInstancia().toString());
	}
	
	// POST que reinicia una tarea del procedimiento, eliminando datos anteriores y creando una nueva vesión de esta
	@PostMapping("/admin/instance/task/reload")
	@Secured({"ROLE_ADMIN", "ROLE_MANAGER"})
	public void reloadTask(Model model, Authentication auth, HttpServletResponse response, @RequestParam BigInteger idInstanciaTasca) throws IOException {
		
		InstanciaTasca instanciaTasca = its.findById(idInstanciaTasca);
		Files.deleteIfExists(Paths.get(this.filePath+instanciaTasca.getEvidencia()));
		InstanciaTasca instanciaTascaNew = new InstanciaTasca();
		instanciaTascaNew.setDataFet(null);
		instanciaTascaNew.setEstat("A");
		instanciaTascaNew.setEvidencia(null);
		instanciaTascaNew.setInstancia(instanciaTasca.getInstancia());
		instanciaTascaNew.setTasca(instanciaTasca.getTasca());
		instanciaTascaNew.setUsuari(null);
		instanciaTascaNew.setText(null);
		instanciaTascaNew.setVersion(0);
		instanciaTascaNew.setIdInstanciaTasca(instanciaTasca.getInstancia().getIdInstancia()
				.multiply(BigInteger.valueOf(10000))
				.add(BigInteger.valueOf(instanciaTasca.getTasca().getIdTascap()))
				.multiply(BigInteger.valueOf(100)));
		
		/* Editable online revisión - inyectar de quien corresponda */
		if(instanciaTasca.getTasca().getTipus().getTipus() == 15) {
			InstanciaTasca itdone = its.findByInstanciaTascap(instanciaTasca.getInstancia().getIdInstancia(), Integer.parseInt(instanciaTasca.getTasca().getOpcions()));
			instanciaTascaNew.setText(itdone.getText());
		}
		
		its.deactivateAll(instanciaTasca.getInstancia().getIdInstancia());
		its.removeAllVersions(instanciaTasca.getInstancia().getIdInstancia(), instanciaTasca.getTasca().getIdTasca());
		
		if(instanciaTascaNew.getTasca().getRol().getNomRol().equals("sys")) {
			instanciaTascaNew = this.its.system(instanciaTascaNew);
		}
		its.save(instanciaTascaNew);
		
		if(!instanciaTasca.getInstancia().getEstat().equals("A")) {
			instanciaTasca.getInstancia().setEstat("A");
			is.save(instanciaTasca.getInstancia());
		}
		
		
		for(Usuari u : us.getInstanceAsignedUsers(instanciaTascaNew.getInstancia().getIdInstancia())) {
			Email email = new Email();
			email.setUsusari(u);
			email.setInstanciaTasca(instanciaTascaNew);
			es.addEmail(email);
		}
		
		response.sendRedirect("/procedure/"+instanciaTasca.getInstancia().getIdInstancia().toString());
	}
	
	// POST que tiene como objetivo reactivar una tarea
	@PostMapping("/admin/instance/task/reactivate")
	@Secured({"ROLE_ADMIN", "ROLE_MANAGER"})
	public void activateTask(Model model, Authentication auth, HttpServletResponse response, @RequestParam BigInteger idInstanciaTasca) throws IOException {
		
		InstanciaTasca instanciaTasca = its.findById(idInstanciaTasca);
		InstanciaTasca instanciaTascaNew = new InstanciaTasca();
		instanciaTascaNew.setDataFet(null);
		instanciaTascaNew.setEstat("A");
		instanciaTascaNew.setEvidencia(null);
		instanciaTascaNew.setInstancia(instanciaTasca.getInstancia());
		instanciaTascaNew.setTasca(instanciaTasca.getTasca());
		instanciaTascaNew.setUsuari(null);
		instanciaTascaNew.setVersion(instanciaTasca.getVersion()+1);
		instanciaTascaNew.setIdInstanciaTasca(instanciaTasca.getIdInstanciaTasca().add(BigInteger.valueOf(1)));
		
		its.deactivateAll(instanciaTasca.getInstancia().getIdInstancia());

		/* Editable online revisión - inyectar de quien corresponda */
		if(instanciaTasca.getTasca().getTipus().getTipus() == 15) {
			instanciaTascaNew.setText(instanciaTasca.getText());
		}
		
		its.save(instanciaTascaNew);
		
		if(!instanciaTasca.getInstancia().getEstat().equals("A")) {
			instanciaTasca.getInstancia().setEstat("A");
			is.save(instanciaTasca.getInstancia());
		}
		
		for(Usuari u : us.getInstanceAsignedUsers(instanciaTascaNew.getInstancia().getIdInstancia())) {
			Email email = new Email();
			email.setUsusari(u);
			email.setInstanciaTasca(instanciaTascaNew);
			es.addEmail(email);
		}
		
		response.sendRedirect("/procedure/"+instanciaTasca.getInstancia().getIdInstancia().toString());
	}
	
	// POST que edita la información de una tarea ya existente
	@PostMapping("/admin/instance/task/edit")
	@Secured({"ROLE_ADMIN", "ROLE_MANAGER"})
	public void editTask(Model model, Authentication auth, HttpServletResponse response, @RequestParam BigInteger idInstanciaTasca) throws IOException {
		
		InstanciaTasca instanciaTasca = its.findById(idInstanciaTasca);
		InstanciaTasca instanciaTascaNew = new InstanciaTasca();
		instanciaTascaNew.setDataFet(null);
		instanciaTascaNew.setEstat("A");
		instanciaTascaNew.setEvidencia(null);
		instanciaTascaNew.setInstancia(instanciaTasca.getInstancia());
		instanciaTascaNew.setTasca(instanciaTasca.getTasca());
		instanciaTascaNew.setUsuari(null);
		instanciaTascaNew.setVersion(instanciaTasca.getVersion()+1);
		instanciaTascaNew.setIdInstanciaTasca(instanciaTasca.getIdInstanciaTasca().add(BigInteger.valueOf(1)));
		instanciaTascaNew.setText(instanciaTasca.getText());
		
		its.deactivateAll(instanciaTasca.getInstancia().getIdInstancia());			
		its.save(instanciaTascaNew);
		
		if(!instanciaTasca.getInstancia().getEstat().equals("A")) {
			instanciaTasca.getInstancia().setEstat("A");
			is.save(instanciaTasca.getInstancia());
		}
		
		for(Usuari u : us.getInstanceAsignedUsers(instanciaTascaNew.getInstancia().getIdInstancia())) {
			Email email = new Email();
			email.setUsusari(u);
			email.setInstanciaTasca(instanciaTascaNew);
			es.addEmail(email);
		}
		
		response.sendRedirect("/procedure/"+instanciaTasca.getInstancia().getIdInstancia().toString());
	}
	
	@GetMapping("/admin/mailing")
	@Secured({"ROLE_ADMIN"})
	public String getMailing(Model model, Authentication auth, HttpServletResponse response) {

		List<Rol> rols = rs.findAll();
		List<Organ> centres = os.getActiveCentres();
		model.addAttribute("centres", centres);
		model.addAttribute("rols", rols);
		
		return "mailing";
	}
	
	@PostMapping("/admin/mailing")
	@Secured({"ROLE_ADMIN"})
	public String sendMails(Model model, Authentication auth, HttpServletResponse response, 
			@RequestParam Integer idRol, @RequestParam("centres[]") List<Integer> centres,
			@RequestParam String subject, @RequestParam String body) {

		List<Usuari> usuaris = us.findByRolCentre(idRol, centres);
		for(Usuari usuari : usuaris) {
			Email email = new Email();
			email.setUsusari(usuari);
			email.setBody(body);
			email.setSubject(subject);
			es.addEmail(email);
		}
		
		List<Rol> rols = rs.findAll();
		List<Organ> centresa = os.getActiveCentres();
		model.addAttribute("centres", centresa);
		model.addAttribute("rols", rols);
		model.addAttribute("sent", true);
		
		return "mailing";
	}
	
	// POST para la creación de un procedimiento nuevo
	@PostMapping("/admin/procedures/new")
	@Secured({"ROLE_ADMIN"})
	public String newProcedure(Model model, Authentication auth, HttpServletResponse response, @RequestParam Map<String,String> params, 
			@RequestParam(name="idTascap[]", required=false) List<String> idTascap, 
			@RequestParam(name="dataLimit[]", required=false) List<String> dataLimit, 
			@RequestParam(name="tipus[]", required=false) List<String> tipus,
			@RequestParam(name="codiEvidencia[]", required=false) List<String> codiEvidencia, 
			@RequestParam(name="idTascaSeg[]", required=false) List<String> idTascaSeg, 
			@RequestParam(name="idTascaSeg2[]", required=false) List<String> idTascaSeg2,
			@RequestParam(name="opcions[]", required=false) List<String> opcions,
			@RequestParam(name="idRol[]", required=false) List<String> idRol, 
			@RequestParam(name="titolCas[]", required=false) List<String> titolCas, 
			@RequestParam(name="titolVal[]", required=false) List<String> titolVal,
			@RequestParam(name="descripcioCas[]", required=false) List<String> descripcioCas, 
			@RequestParam(name="descripcioVal[]", required=false) List<String> descripcioVal,
			@RequestParam(name="nomEvidenciaCas[]", required=false) List<String> nomEvidenciaCas, 
			@RequestParam(name="nomEvidenciaVal[]", required=false) List<String> nomEvidenciaVal,
			@RequestParam(name="idPlantilla[]", required=false) List<String> idPlantilla,
			@RequestParam(name="informe[]", required=false) List<Boolean> informe) throws NumberFormatException, ParseException {
	
		Proces p = new Proces();
		p.setIdProces(Integer.parseInt(params.get("idProces")));
		p.setNomProces(params.get("nomProces"));
		p.setVersio(params.get("versio"));
		p.setComentaris(params.get("comentaris"));
		p.setSubTitol(params.get("subTitol"));
		p.setAmbit(params.get("ambit"));
		p.setTitolCas(params.get("titolCas").equals(".") ? "" : params.get("titolCas"));
		p.setTitolVal(params.get("titolVal").equals(".") ? "" : params.get("titolVal"));
		p.setDescripcioCas(params.get("descripcioCas").equals(".") ? "" : params.get("descripcioCas"));
		p.setDescripcioVal(params.get("descripcioVal").equals(".") ? "" : params.get("descripcioVal"));
		p.setCursActivacio(Integer.parseInt(params.get("cursActivacio")));
		p.setCursAvaluat(Integer.parseInt(params.get("cursAvaluat")));
		
		ps.save(p);
		
		if(idTascaSeg != null) {
			for(Integer i = 0; i < idTascap.size(); i++) {
				Tasca t = new Tasca();
				t.setIdTasca((p.getIdProces()*10000)+Integer.parseInt(idTascap.get(i)));
				t.setProces(p);
				t.setIdTascap(Integer.parseInt(idTascap.get(i)));
				t.setIdTascaSeg(Integer.parseInt(idTascaSeg.get(i)));
				t.setIdTascaSeg2(idTascaSeg2.get(i).equals(".") ? null : Integer.parseInt(idTascaSeg2.get(i)));
				t.setOpcions(opcions.get(i));
				t.setTitolCas(titolCas.get(i).equals(".") ? "" : titolCas.get(i).replace("[comma]", ","));
				t.setDescripcioCas(descripcioCas.get(i).equals(".") ? "" : descripcioCas.get(i).replace("[comma]", ","));
				t.setTitolVal(titolVal.get(i).equals(".") ? "" : titolVal.get(i).replace("[comma]", ","));
				t.setDescripcioVal(descripcioVal.get(i).equals(".") ? "" : descripcioVal.get(i).replace("[comma]", ","));
				t.setNomEvidenciaCas(nomEvidenciaCas.get(i).equals(".") ? "" : nomEvidenciaCas.get(i).replace("[comma]", ","));
				t.setNomEvidenciaVal(nomEvidenciaVal.get(i).equals(".") ? "" : nomEvidenciaVal.get(i).replace("[comma]", ","));
				t.setDataLim(new SimpleDateFormat(DDMMYYYY).parse(dataLimit.get(i)));
				t.setTipus(tps.findOne(Integer.parseInt(tipus.get(i))));
				if(t.getTipus().getTipus() == 11 || t.getTipus().getTipus() == 15) {
					t.setCodiEvidencia(idPlantilla.get(i));
				}
				else {
					t.setCodiEvidencia(codiEvidencia.get(i).equals(".") ? "" : codiEvidencia.get(i).replace("[comma]", ","));
				}
				
				t.setRol(rs.findOne(Integer.parseInt(idRol.get(i))));
				t.setInforme(informe.get(i));
				
				ts.save(t);
			}
		}
		
		this.loadProceduresData(model);
		
		return "adminProcedures";
	}
	
	// POST para editar un procedimiento ya existente
	@PostMapping("/admin/procedures/edit")
	@Secured({"ROLE_ADMIN"})
	public String editProcedure(Model model, Authentication auth, HttpServletResponse response, @RequestParam Map<String,String> params, 
			@RequestParam(name="idTascap[]", required=false) List<String> idTascap, 
			@RequestParam(name="dataLimit[]", required=false) List<String> dataLimit, 
			@RequestParam(name="tipus[]", required=false) List<String> tipus,
			@RequestParam(name="codiEvidencia[]", required=false) List<String> codiEvidencia, 
			@RequestParam(name="idTascaSeg[]", required=false) List<String> idTascaSeg, 
			@RequestParam(name="idTascaSeg2[]", required=false) List<String> idTascaSeg2,
			@RequestParam(name="opcions[]", required=false) List<String> opcions,
			@RequestParam(name="idRol[]", required=false) List<String> idRol, 
			@RequestParam(name="titolCas[]", required=false) List<String> titolCas, 
			@RequestParam(name="titolVal[]", required=false) List<String> titolVal,
			@RequestParam(name="descripcioCas[]", required=false) List<String> descripcioCas, 
			@RequestParam(name="descripcioVal[]", required=false) List<String> descripcioVal,
			@RequestParam(name="nomEvidenciaCas[]", required=false) List<String> nomEvidenciaCas, 
			@RequestParam(name="nomEvidenciaVal[]", required=false) List<String> nomEvidenciaVal,
			@RequestParam(name="idPlantilla[]", required=false) List<String> idPlantilla,
			@RequestParam(name="informe[]", required=false) List<Boolean> informe) 
					throws NumberFormatException, ParseException {

		Proces p = ps.findByID(Integer.parseInt(params.get("idProces")));
		p.setNomProces(params.get("nomProces"));
		p.setVersio(params.get("versio"));
		p.setComentaris(params.get("comentaris"));
		p.setSubTitol(params.get("subTitol"));
		p.setAmbit(params.get("ambit"));
		p.setTitolCas(params.get("titolCas").equals(".") ? "" : params.get("titolCas"));
		p.setTitolVal(params.get("titolVal").equals(".") ? "" : params.get("titolVal"));
		p.setDescripcioCas(params.get("descripcioCas").equals(".") ? "" : params.get("descripcioCas"));
		p.setDescripcioVal(params.get("descripcioVal").equals(".") ? "" : params.get("descripcioVal"));
		p.setCursActivacio(Integer.parseInt(params.get("cursActivacio")));
		p.setCursAvaluat(Integer.parseInt(params.get("cursAvaluat")));
		
		ps.save(p);
		
		if(idTascaSeg != null) {
			for(Tasca t : ts.findByProces(p.getIdProces())) {
				if(!idTascap.contains(Integer.toString(t.getIdTascap()))) {
					ts.delete(t);
				}
			}
				
			for(Integer i = 0; i < idTascap.size(); i++) {
				Tasca t;
				try {
					t = ts.getByID((p.getIdProces()*10000)+Integer.parseInt(idTascap.get(i)));
					if(t == null) {
						t = new Tasca();
						t.setIdTasca((p.getIdProces()*10000)+Integer.parseInt(idTascap.get(i)));
						t.setProces(p);
						t.setIdTascap(Integer.parseInt(idTascap.get(i)));
					}
				}
				catch(Exception e) {
					t = new Tasca();
					t.setIdTasca((p.getIdProces()*10000)+Integer.parseInt(idTascap.get(i)));
					t.setProces(p);
					t.setIdTascap(Integer.parseInt(idTascap.get(i)));
				}
	
				t.setIdTascaSeg(Integer.parseInt(idTascaSeg.get(i)));
				t.setIdTascaSeg2(idTascaSeg2.get(i).equals(".") ? null : Integer.parseInt(idTascaSeg2.get(i)));
				t.setOpcions(opcions.get(i));
				t.setTitolCas(titolCas.get(i).equals(".") ? "" : titolCas.get(i).replace("[comma]", ","));
				t.setDescripcioCas(descripcioCas.get(i).equals(".") ? "" : descripcioCas.get(i).replace("[comma]", ","));
				t.setTitolVal(titolVal.get(i).equals(".") ? "" : titolVal.get(i).replace("[comma]", ","));
				t.setDescripcioVal(descripcioVal.get(i).equals(".") ? "" : descripcioVal.get(i).replace("[comma]", ","));
				t.setNomEvidenciaCas(nomEvidenciaCas.get(i).equals(".") ? "" : nomEvidenciaCas.get(i).replace("[comma]", ","));
				t.setNomEvidenciaVal(nomEvidenciaVal.get(i).equals(".") ? "" : nomEvidenciaVal.get(i).replace("[comma]", ","));
				t.setDataLim(new SimpleDateFormat(DDMMYYYY).parse(dataLimit.get(i)));
				t.setTipus(tps.findOne(Integer.parseInt(tipus.get(i))));
				if(t.getTipus().getTipus() == 11 || t.getTipus().getTipus() == 15) {
					t.setCodiEvidencia(idPlantilla.get(i));
				}
				else {
					t.setCodiEvidencia(codiEvidencia.get(i).equals(".") ? "" : codiEvidencia.get(i).replace("[comma]", ","));
				}
				t.setRol(rs.findOne(Integer.parseInt(idRol.get(i))));
				t.setInforme(informe.get(i));
				ts.save(t);
			}
		}

		this.loadProceduresData(model);
		
		return "adminProcedures";
	}
	
	// POST que elimina un procedimiento
	@PostMapping("/admin/procedures/remove")
	@Secured({"ROLE_ADMIN"})
	public String removeProcedure(Model model, Authentication auth, HttpServletResponse response, @RequestParam("idProces") Integer idProces){

		Proces p = ps.findByID(idProces);
		for(Tasca t : ts.findByProces(p.getIdProces())) {
			ts.delete(t);
		}
		ps.delete(p);
		
		this.loadProceduresData(model);
		
		return "adminProcedures";
	}
	
	// POST que le eliminar un usuario concreto del sitema
	@PostMapping("/admin/userrole/remove")
	@Secured({"ROLE_ADMIN", "ROLE_MANAGER"})
	public void removeUserrole(Model model, Authentication auth, HttpServletResponse response, HttpSession session, @RequestParam("idRol") Integer idRol, 
			@RequestParam("usuari") String usuari, @RequestParam("lugar") Integer lugar, @RequestParam("tlugar") String tlugar) throws IOException{
		
		UsuarisRol u = urs.findActive(idRol, usuari, lugar, tlugar);
		if(u != null) {
			u.setVigent(false);
			u.setFin(Calendar.getInstance().getTime());
			urs.save(u);
		}
		
		List<Integer> respCentres = new ArrayList<Integer>();
		List<Integer> respTitulacions = new ArrayList<Integer>();
		if(tlugar.equals("C")) {
			respCentres.add(lugar);
			session.setAttribute("respCentres", respCentres);
			session.setAttribute("respTitulacions", respTitulacions);
		}
		else {
			Organ titulacio = os.findByID(tlugar, lugar);
			respCentres.add(titulacio.getOrgan().getId().getLugar());
			respTitulacions.add(titulacio.getId().getLugar());
			session.setAttribute("respCentres", respCentres);
			session.setAttribute("respTitulacions", respTitulacions);
		}
		
		
		response.sendRedirect("/managers");
	}
	
	// POST para añadir un nuevo usuario al sistema
	@PostMapping("/admin/userrole/new")
	@Secured({"ROLE_ADMIN", "ROLE_MANAGER"})
	public void newUserrole(Model model, Authentication auth, HttpServletResponse response, HttpSession session, @RequestParam("idRol") Integer idRol, 
			@RequestParam(name="usuari", required=false) String usuari, @RequestParam("centre") Integer idCentre, 
			@RequestParam(name="titulacio", required=false) Integer idTitulacio, @RequestParam Map<String,String> params) throws IOException{
		
		if(usuari == null && params.get("username") != null) {
			Usuari x = new Usuari();
			x.setCognoms(params.get("lastname"));
			x.setNom(params.get("firstname"));
			x.setUsuari(params.get("username"));
			x.setEmail(params.get("email"));
			x.setLdap(true);
			this.us.save(x);
			usuari = x.getUsuari();
		}
		
		Rol rol = rs.findOne(idRol);
		Integer lugar = null;
		String tlugar = null;
		boolean exists = false;
		if(rol.getAmbit().equals("C")) {
			lugar = idCentre;
			tlugar = "C";
			UsuarisRol u = urs.findLast(idRol, usuari, lugar, tlugar);
			Integer num = urs.findLastNum(idRol, lugar, tlugar);
			num = num == null ? 0 : num;
			if(u != null) {
				if(!u.getVigent()) {
					UsuarisRol r = new UsuarisRol();
					r.setFin(null);
					r.setInici(Calendar.getInstance().getTime());
					r.setUsuari(u.getUsuari());
					r.setOrgan(u.getOrgan());
					r.setRol(u.getRol());
					r.setVigent(true);
					r.setSupervisor(null);
					r.setNum(num+1);
					r.setIdUsuariRol(Integer.parseInt(Integer.toString(lugar)+(idRol < 10 ? "0" : "")+Integer.toString(idRol)+(num+1 < 10 ? "0" : "")+Integer.toString(num+1)));
					urs.save(r);
				}
				else {
					exists = true;
				}
			}
			else {
				UsuarisRol r = new UsuarisRol();
				r.setFin(null);
				r.setInici(Calendar.getInstance().getTime());
				r.setUsuari(us.findByUsername(usuari));
				r.setOrgan(os.findByID(tlugar, lugar));
				r.setRol(rs.findOne(idRol));
				r.setVigent(true);
				r.setSupervisor(null);
				r.setNum(num+1);
				r.setIdUsuariRol(Integer.parseInt(Integer.toString(lugar)+(idRol < 10 ? "0" : "")+Integer.toString(idRol)+(num+1 < 10 ? "0" : "")+Integer.toString(num+1)));
				urs.save(r);
			}
		}
		else {
			tlugar = "T";
			UsuarisRol u = urs.findLast(idRol, usuari, idTitulacio, tlugar);
			Integer num = urs.findLastNum(idRol, idTitulacio, tlugar);
			num = num == null ? 0 : num;
			if(u != null) {
				if(!u.getVigent()) {
					UsuarisRol r = new UsuarisRol();
					r.setFin(null);
					r.setInici(Calendar.getInstance().getTime());
					r.setUsuari(u.getUsuari());
					r.setOrgan(u.getOrgan());
					r.setRol(u.getRol());
					r.setVigent(true);
					r.setSupervisor(null);
					r.setNum(num+1);
					r.setIdUsuariRol(Integer.parseInt(Integer.toString(idTitulacio)+(idRol < 10 ? "0" : "")+Integer.toString(idRol)+(num+1 < 10 ? "0" : "")+Integer.toString(num+1)));
					urs.save(r);
				}
				else {
					exists = true;
				}
			}
			else {
				UsuarisRol r = new UsuarisRol();
				r.setFin(null);
				r.setInici(Calendar.getInstance().getTime());
				r.setUsuari(us.findByUsername(usuari));
				r.setOrgan(os.findByID(tlugar, idTitulacio));
				r.setRol(rs.findOne(idRol));
				r.setVigent(true);
				r.setSupervisor(null);
				r.setNum(num+1);
				r.setIdUsuariRol(Integer.parseInt(Integer.toString(idTitulacio)+(idRol < 10 ? "0" : "")+Integer.toString(idRol)+(num+1 < 10 ? "0" : "")+Integer.toString(num+1)));
				urs.save(r);
			}
		}
		
		List<Integer> respCentres = new ArrayList<Integer>();
		respCentres.add(idCentre);
		session.setAttribute("respCentres", respCentres);
		List<Integer> respTitulacions = new ArrayList<Integer>();
		if(idTitulacio != null) {
			respTitulacions.add(idTitulacio);
		}
		session.setAttribute("respTitulacions", respTitulacions);

		if(exists) {
			session.setAttribute("roleExists", true);
		}
		
		
		response.sendRedirect("/managers");
	}
	
	@GetMapping("/admin/templates2")
	@Secured({"ROLE_ADMIN", "ROLE_TESTER"})
	public String getTemplates(Model model, Authentication auth, HttpServletResponse response) {

		this.loadInstanceData(model);
		return "adminTemplates";
	}
	
	// GET que recoge todas las plantillas actuales del sistema
	@GetMapping("/admin/templates")
	@Secured({"ROLE_ADMIN", "ROLE_TESTER"})
	public String getTemplates2(Model model, Authentication auth, HttpServletResponse response) {
					
		File[] files = Stream.concat(Arrays.stream(new File(this.templatePath).listFiles()), 
							         Arrays.stream(new File(this.templatePath+"/T1/").listFiles()))
					         .toArray(File[]::new);
		files = Stream.concat(Arrays.stream(files), 
		         			  Arrays.stream(new File(this.templatePath+"/T2/").listFiles()))
				.distinct()
				.toArray(File[]::new);
		
		List<String> evs = new ArrayList<String>();
		for(File f : files) {
			
			String e = f.getName().replace(".docx", "");
			if(f.getPath().contains("/T1/")) {
				e = e + " (G)";
			}
			else if(f.getPath().contains("/T2/")) {
				e = e + " (M)";
			}
			
			if(!e.endsWith("_") && !e.contains(".old")) {
				evs.add(e.replace("_", "."));
			}
			
		}
		
		
		this.loadInstanceData(model);
		model.addAttribute("currentYear", LocalDate.now().getYear());
		model.addAttribute("evs", evs);
		return "adminTemplates2";
	}
	
	public void loadTemplateData(Model model) {
		model.addAttribute("evs", this.ts.getAllAvailableEvidences());
	}
	
	// POST que redefine que indicadores están asociados a una evidencia dentro de un proceso
	@PostMapping("/admin/templates/inds/update")
	@Secured({"ROLE_ADMIN"})
	public String updateTemplateInds(Model model, Authentication auth, HttpServletResponse response,
			@RequestParam(name="indicador[]", required=true) List<String> indicador,
			@RequestParam(name="enquesta[]", required=true) List<String> enquesta,
			@RequestParam(name="media[]", required=true) List<String> media,
			@RequestParam(name="evidencia", required=true) String evidencia,
			@RequestParam(name="proces", required=true) String proces
			) {
		
		eies.removeByProcesEvidencia(proces, evidencia);
		
		for(Integer i = 0; i < indicador.size(); i++) {
			EvidenciaIndicadorEnquesta e = new EvidenciaIndicadorEnquesta();
			EvidenciaIndicadorEnquestaPK eid = new EvidenciaIndicadorEnquestaPK();
			eid.setEnquesta(enquesta.get(i)); 
			eid.setEvidencia(evidencia);
			eid.setIndicador(indicador.get(i));
			eid.setProces(proces);
			e.setId(eid);
			e.setMedia(media.get(i));
			eies.save(e);
		}
			
		return "blank";
	}
	
	// GET para abrir el editor de plantillas
	@GetMapping("/admin/editor")  
	@Secured({"ROLE_ADMIN", "ROLE_TESTER"})
	public String getTemplateEditor(Model model, Authentication auth, HttpServletResponse response) {

		List<String> inds = this.ies.findTypes();
		List<Plantilla> templates = this.plc.findAll();
		model.addAttribute("templates", templates);
		model.addAttribute("inds", inds);
		this.loadInstanceData(model);
		if(((Usuari)auth.getPrincipal()).isDataTest()) {
			return "testerTemplateEditor";
		}
		return "adminTemplateEditor";
	}
	
	@GetMapping("/admin/editor/test")  
	@Secured({"ROLE_ADMIN", "ROLE_TESTER"})
	public String testTemplateEditor(Model model, Authentication auth, HttpServletResponse response,
			@RequestParam Integer idPlantilla, @RequestParam Integer idTitulacio, @RequestParam Integer idCentre, @RequestParam Integer curs) {
		
		Plantilla p = plc.findByID(idPlantilla);
		TemplateDataDTO td = new TemplateDataDTO(idTitulacio, idCentre, curs, p.getText());
		String text = plc.addTemplateData2(td);
		model.addAttribute("text", text);
		
		return "adminTemplateTest";
	}
	
	// GET para la carga del calendario
	@GetMapping("/admin/calendar")  
	@Secured({"ROLE_ADMIN"})
	public String calendar(Model model, Authentication auth, HttpServletResponse response) {

		this.loadInstanceData(model);
		return "adminCalendar";
	}
	
	@GetMapping("/admin/acredita/{curs}/{grup}/{tambit}")  
	@ResponseBody
	@Secured({"ROLE_ADMIN", "ROLE_MANAGER"})
	public List<AcreditacioTransfer> acreditacionsByCurs(Model model, Authentication auth, HttpServletResponse response,
			@PathVariable Integer curs, @PathVariable Integer grup, @PathVariable String tambit) {
		
		List<AcreditacioTransfer> alist = new ArrayList<AcreditacioTransfer>();
		
		if(grup == 0) {
			for(Acreditacio a : this.as.getByCurs(curs)) {
				Organ o = os.findByID(a.getTlugar(), a.getLugar());
				alist.add(new AcreditacioTransfer(a, o));
			}
			return alist;
		}
		else {
			if(tambit.equals("A")) {
				for(Acreditacio a : this.as.getByCursGrup(curs, grup)) {
					Organ o = os.findByID(a.getTlugar(), a.getLugar());
					alist.add(new AcreditacioTransfer(a, o));
				}
			}
			else {
				for(Acreditacio a : this.as.getByCursGrupTambit(curs, grup, tambit)) {
					Organ o = os.findByID(a.getTlugar(), a.getLugar());
					alist.add(new AcreditacioTransfer(a, o));
				}
			}
			return alist;
		}
	}
	
	@PostMapping("/admin/acredita")  
	@ResponseBody
	@Secured({"ROLE_ADMIN", "ROLE_MANAGER"})
	public Acreditacio UpdateAcreditacio(Model model, Authentication auth, HttpServletResponse response, 
									@RequestParam String tlugar, @RequestParam Integer lugar, 
									@RequestParam Integer grupCurs, @RequestParam Integer grupNum, @RequestParam Integer cursImpla,
									@RequestParam String dataAcred, @RequestParam String dataRenov, @RequestParam String dataSegui,
									@RequestParam String dataVerif, @RequestParam Boolean recom, @RequestParam Boolean segui) throws ParseException {
		
		Acreditacio a = this.as.getById(tlugar, lugar);
		a.setGrupCurs(grupCurs);
		a.setGrupNum(grupNum);
		a.setDataAcred(new SimpleDateFormat(DDMMYYYY).parse(dataAcred));
		a.setDataRenov(new SimpleDateFormat(DDMMYYYY).parse(dataRenov));
		a.setDataSegui(new SimpleDateFormat(DDMMYYYY).parse(dataSegui));
		a.setDataVerif(new SimpleDateFormat(DDMMYYYY).parse(dataVerif));
		a.setCursImpla(cursImpla);
		a.setRecom(recom);
		a.setSegui(segui);
		a = as.save(a);
		
		return a;
	}
	
}
