package parziale.p251110;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.TreeMap;

public class Clinica {
	
	ArrayList<Paziente> pazienti = new ArrayList<Paziente>();
	
	// 1. Numero di pazienti Ricoverati
	public int pazientiRicoverati() {
		return pazienti.size();
	}
	
	// 2. Inserimento del paziente
	/*
	 * Dal momento che non ci è permesso adoperare 
	 * TreeSet per l'ordine e per l'unicità
	 */
	public boolean ricoveraPaziente(Paziente paziente) {
		// Se il paziente è nullo, nulla verrà aggiunto
		if (paziente == null) return false;
		
		// Controllo se il paziente è già presente nella lista ricoveri
		Iterator<Paziente> it = pazienti.iterator();
		while (it.hasNext()) {
			Paziente current = it.next();
			if (paziente.equals(current)) return false;	// Se è già presente un paziente con id uguale allora non viene aggiunto e ritorna false
		}
		
		// Aggiunta del paziente 
		ListIterator<Paziente> lit = pazienti.listIterator();
		while (lit.hasNext()) {
			Paziente current = lit.next();
			int cmp = current.compareTo(paziente);
			if (cmp > 0) {
				lit.previous();
				lit.add(paziente);
				return true;
			}
		}
		
		lit.add(paziente);
		return true;
	}
	
	// 3. Dimissione
	public Paziente dimettiPaziente(String id, int annoNascita) {
		if (id == null || annoNascita <= 0) return null;
		Paziente tmp = new Paziente(id, annoNascita);
		
		Iterator<Paziente> iterator = pazienti.iterator();
		while (iterator.hasNext()) {
			Paziente current = iterator.next();
			int cmp = current.compareTo(tmp);
			if (cmp == 0) {
				// Paziente da rimuovere
				iterator.remove();
				return current;
			}
			if (cmp > 0) return null;
		}
		
		return null;
	}
	
	// 4. Età media
	public int etaMedia() {
		if (pazienti.isEmpty()) return 0;
		
		int currentDate = LocalDate.now().getYear();
		int avg = 0;
		
		Iterator<Paziente> it = pazienti.iterator();
		while (it.hasNext()) {
			int ageYear = currentDate - it.next().getAnnoNascita();
			avg += ageYear;
		}
		
		return avg / pazienti.size();
	}
	
	// 5. Età più rappresenta
	public int etaMediaPiuRappresentata() {
		if (pazienti.isEmpty()) return 0;
		
		int currentDate = LocalDate.now().getYear();
		TreeMap<Integer, Integer> listaEta = new TreeMap<Integer, Integer>();
		
		Iterator<Paziente> it = pazienti.iterator();
		while (it.hasNext()) {
			Paziente current = it.next();
			int currentAge = currentDate - current.getAnnoNascita(); 
			
			if (listaEta.get(currentAge) == null) listaEta.put(currentAge, 1);
			else listaEta.put(currentAge, listaEta.get(currentAge) + 1);
		}
		
		int maxAge = 0;
		int maxFrequency = 0;
		
		for (Integer i : listaEta.keySet()) {
			int currentFrequency = listaEta.get(i);
			
			if (currentFrequency > maxFrequency) {
				maxFrequency = currentFrequency;
				maxAge = i;
			}
			
		}
		
		return maxAge;
	}
	
	// 6. Ricoverati ordinati per codice
	public ArrayList<Paziente> ricoveratiOrdinatiPerCodice() {
		ArrayList<Paziente> ricoverati = new ArrayList<Paziente>(pazienti);
	
		ricoverati.sort(new Comparator<Paziente>() {
			@Override
			public int compare(Paziente p1, Paziente p2) {
				String id1 = p1.getId();
				String id2 = p2.getId();
				return id1.compareTo(id2);
			}
		});
		
		return ricoverati;
	}
	
	// 7. Distribuzione pazienti per anno di nascita
	public Map<Integer, Integer> pazientiPerAnnoDiNascita() {
		// AnnoNascita, NumeroPazienti
		Map<Integer, Integer> pazientiPerAnnoDiNascita = new TreeMap<Integer, Integer>();		// Si usa TreeMap per avere una vista già ordinata di anni
		
		if (pazienti.isEmpty()) return pazientiPerAnnoDiNascita;
		
		Iterator<Paziente> it = pazienti.iterator();
		while (it.hasNext()) {
			Paziente current = it.next();
			int annoNascita = current.getAnnoNascita();
			
			if (pazientiPerAnnoDiNascita.get(annoNascita) == null) pazientiPerAnnoDiNascita.put(annoNascita, 1);
			else pazientiPerAnnoDiNascita.put(annoNascita, pazientiPerAnnoDiNascita.get(annoNascita) + 1);
		}
		
		return pazientiPerAnnoDiNascita;
	}
	
	public static List<Clinica> ordinaListaClinicaPerNumeroPazienti(List <Clinica> cliniche) {
		if (cliniche == null) throw new NullPointerException();
		
		cliniche.sort(new Comparator<Clinica>() {
			@Override
			public int compare(Clinica c1, Clinica c2) {
				int pazienti1 = c1.pazienti.size();
				int pazienti2 = c2.pazienti.size();
				return pazienti1 - pazienti2;
			}
		});
		
		return cliniche;
	}
}
