package it.unicam.pizzeria4.sala;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;

import it.unicam.pizzeria4.servizio.GestoreComande;
import it.unicam.pizzeria4.util.*;

public class Sala {

	private static Sala instance;

	private ArrayList<Tavolo> tavoliLiberi;
	private ArrayList<Tavolo> tavoliOccupati;
	private ArrayList<TavoloSala> tavoliSala;
	private ArrayList<TavoloAsporto> tavoliAsporto;
	private GestoreComande gComande;

	private Sala() {
		this.tavoliLiberi = new ArrayList<Tavolo>();
		this.tavoliOccupati = new ArrayList<Tavolo>();
		this.tavoliSala = new ArrayList<TavoloSala>();
		this.tavoliAsporto = new ArrayList<TavoloAsporto>();
		this.gComande = GestoreComande.getInstance();
	}

	public static Sala getInstance() {
		if (instance == null) {
			instance = new Sala();
		}
		return instance;
	}

	public void addTavolo(Tavolo tavolo) {
		tavoliLiberi.add(tavolo);
	}

	public ArrayList<DettagliTavolo> assegnazioneTavolo() {
		ArrayList<DettagliTavolo> statoSala = new ArrayList<DettagliTavolo>();
		Tavolo tavolo;
		DettagliTavolo datiTavolo;
		Iterator<Tavolo> tli = tavoliLiberi.iterator();
		while (tli.hasNext()) {
			tavolo = tli.next();
			datiTavolo = new DettagliTavolo(tavolo.getID(), "immagine predefinita", tavolo.getCapienza(), false, false);
			statoSala.add(datiTavolo);
		}
		TavoloSala tavoloSala;
		Iterator<TavoloSala> tls = tavoliSala.iterator();
		while (tls.hasNext()) {
			tavoloSala = tls.next();
			if (tavoloSala.isComposito()) {
				datiTavolo = new DettagliTavolo(tavoloSala.getID(), "immagine predefinita", tavoloSala.getCapienza(),
						true, true);
				Tavolo[] tavoliComponenti = tavoloSala.getTavoliComponenti();
				for (int i = 0; i < tavoliComponenti.length; i++) {
					datiTavolo.addTavoloComponente(tavoliComponenti[i].getID());
				}
			} else {
				datiTavolo = new DettagliTavolo(tavoloSala.getID(), "immagine predefinita", tavoloSala.getCapienza(),
						true, false);

			}
			statoSala.add(datiTavolo);
		}
		return statoSala;
	}

	/**
	 * 
	 * @param numCoperti
	 */
	public ArrayList<String> getTavolo(int numCoperti) {
		return this.suggerisciTavoli(numCoperti);
	}

	/**
	 * 
	 * @param idTavolo
	 */
	public void riservaTavolo(String idTavolo, int numCoperti) {
		Tavolo tavolo = occupaTavolo(idTavolo);
		if (tavolo != null) {
			String idComanda = gComande.newComandaID(numCoperti);
			TavoloSala tavoloSala = new TavoloSala(tavolo, idComanda);
			tavoliSala.add(tavoloSala);
			System.out.println("[INFO] Il tavolo " + tavoloSala.getID() + " Ã¨ stato assegnato");
		}
	}

	public void riservaTavolo(String[] idTavolo, int numCoperti) {
		Tavolo[] tavoli = new Tavolo[idTavolo.length];
		Tavolo tavolo;
		int trovati = 0;
		for (int i = 0; i < idTavolo.length; i++) {
			tavolo = occupaTavolo(idTavolo[i]);
			if (tavolo != null) {
				tavoli[i] = tavolo;
				trovati++;
			} else {
				break;
			}
		}
		if (trovati < idTavolo.length) {
			System.out.println(
					"[ERROR]: Attenzione alcuni o tutti i codici inseriti non corrispondono a tavoli liberi. il tavolo composito non Ã¨ stato creato ");
			for (int i = 0; i < trovati; i++) {
				liberaTavolo(tavoli[i]);
			}
			return;
		}
		String idComanda = gComande.newComandaID(numCoperti);
		String newID = this.generaStampaID();
		TavoloSala tavoloSala = new TavoloSala(tavoli, idComanda);
		tavoloSala.setID(newID);
		tavoliSala.add(tavoloSala);
		System.out.println("[INFO] Generato nuovo ID per tavolo composito: " + newID);
		if (trovati < idTavolo.length)
			System.out.println("[ERROR]: Attenzione alcuni codici inseriti non corrispondevano a tavoli esistenti");
	}

	public Tavolo occupaTavolo(String idTavolo) {
		Iterator<Tavolo> tli = tavoliLiberi.iterator();
		Tavolo tavolo = null;
		boolean trovato = false;
		while (!trovato && tli.hasNext()) {
			tavolo = tli.next();
			if (tavolo.getID().equals(idTavolo)) {
				tavoliLiberi.remove(tavolo);
				tavoliOccupati.add(tavolo);
				trovato = true;
			}
		}
		if (trovato) {
			return tavolo;
		} else {
			System.out.println("[ERROR]: Il tavolo con ID " + idTavolo + " non risulta essere tra i liberi!");
			return null;
		}

	}

	public void liberaTavolo(Tavolo tavolo) {
		boolean rimosso = tavoliOccupati.remove(tavolo);
		if (!rimosso) {
			System.out.println("[INFO]: Attenzione il tavolo da liberare non risulta tra gli occupati");
			return;
		}
		tavoliLiberi.add(tavolo);
	}

	/**
	 * 
	 * @param numCoperti
	 */
	public ArrayList<String> suggerisciTavoli(int numCoperti) {
		ArrayList<String> selezioneTavoli = new ArrayList<String>();
		Iterator<Tavolo> tli = tavoliLiberi.iterator();
		Tavolo tavolo;
		while (tli.hasNext()) {
			tavolo = tli.next();
			if (tavolo.getCapienza() >= numCoperti) {
				selezioneTavoli.add(tavolo.getID());
			}
		}
		return selezioneTavoli;
	}

	public String generaStampaID() {
		Random random = new Random();
		Integer ID = random.nextInt(10000);
		return ID.toString();
	}

	/**
	 * 
	 * @param idTavolo
	 */
	public DettagliComanda compilaComandaTavolo(String idTavolo) {
		TavoloSala tavoloSala = this.getTavoloSala(idTavolo);
		if (tavoloSala == null)
			return null;
		String idComanda = tavoloSala.getComanda();
		DettagliComanda dettagli = gComande.getDettagliComanda(idComanda);
		return dettagli;
	}

	public TavoloSala getTavoloSala(String idTavolo) {
		Iterator<TavoloSala> tsi = tavoliSala.iterator();
		TavoloSala tavoloSala = null;
		boolean trovato = false;
		while (tsi.hasNext()) {
			tavoloSala = tsi.next();
			if (tavoloSala.getID().equals(idTavolo))
				trovato = true;
		}
		if (trovato) {
			return tavoloSala;
		} else {
			System.out.println("[ERROR]: Il tavolo con ID " + idTavolo + " non esiste!");
			return null;
		}
	}

	public void setSala(ArrayList<DatiTavolo> tavoli) {
		Iterator<DatiTavolo> dti = tavoli.iterator();
		Tavolo tavolo;
		DatiTavolo dTavolo;
		while (dti.hasNext()) {
			dTavolo = dti.next();
			tavolo = new Tavolo(dTavolo.getCodice(), dTavolo.getCapienza());
			tavolo.setSala(dTavolo.getSala());
			tavoliLiberi.add(tavolo);
		}
	}
	
	public void liberaTavolo(String idTavolo) {
		
		Iterator<TavoloSala> iTvaoliSala = tavoliSala.iterator();
		TavoloSala tavoloSala = null;
		boolean esiste = false;
		while (iTvaoliSala.hasNext()) {
			tavoloSala = iTvaoliSala.next();
			if (tavoloSala.getID().equals(idTavolo))
				esiste = true;
		}
		if (esiste) {
		    if(!tavoloSala.isComposito()) {
		    System.out.println("[INFO]: Il tavolo con ID " + idTavolo + " non ci sono tavoli associati ");
			Iterator<Tavolo> tavoliOcc = tavoliOccupati.iterator();
			Tavolo tavolo = null;
			boolean trovato = false;
			while (!trovato && tavoliOcc.hasNext()) {
				tavolo = tavoliOcc.next();
				if (tavolo.getID().equals(idTavolo)) {
					tavoloSala.setTipo(TipoTavoloAttivo.inpagamento);
					tavoliOccupati.remove(tavolo);
					tavoliLiberi.add(tavolo);
					trovato = true;
				}
			}
		    
			if (!trovato) {
				System.out.println("[ERRORE]: Il tavolo con ID " + idTavolo + " non è occupato");
			}
		    } else
		    {
		    	System.out.println("[INFO]: Il tavolo con Codice " + idTavolo + " e\' composito, attività di rimozione tavoli compisti in corso ...");
		    	Iterator<Tavolo> tavoliOcc = tavoliOccupati.iterator();
				Tavolo tavolo = null;
				boolean trovato = false;
				while (!trovato && tavoliOcc.hasNext()) {
					tavolo = tavoliOcc.next();
					if (tavolo.getID().equals(idTavolo)) {
						tavoloSala.setTipo(TipoTavoloAttivo.inpagamento);
						Tavolo[] tavoliComp;
						tavoliComp = tavoloSala.getTavoliComponenti();
						for(int i=0; i<tavoliComp.length; i++) {
						liberaTavolo(tavoliComp[i]);
						trovato = true;
						}
					}
				}
			    
				if (!trovato) {
					System.out.println("[ERROR]: Il tavolo con ID " + idTavolo + " noon è tra gli occupati!");
				}
		    }
			
		
		} else {
			System.out.println("[ERROR]: Il tavolo con ID " + idTavolo + " non esiste!");
		}
		
		
	}	
	
}
