package Parkhaus;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

/* Parkhaus klasse
 *  - Extern klasse dient als System
 *  - mit diseser Kalsse integriert der User (Autofahrer)
 * 
 */
public class Parkhaus {
	private ArrayList<Fahrzeug> fahrzeuge;
	private Set<Fahrzeug> fahrzeugeMitSchulden;
	private int maxPlaetze;
	private SimpleDateFormat sdf;
	private Fahrzeug fahrzeug;
	private double betragAktuellesAuto;

	Parkhaus() {
		this.fahrzeuge = new ArrayList<>();
		this.fahrzeugeMitSchulden = new HashSet<>();
		this.maxPlaetze = 180;
		this.sdf = new SimpleDateFormat("dd.MM.yyyy, HH:mm");
	}

	public String einfahren(String kennzeichen, String einfahrtzeit) throws ParseException {
		Date einfahrt;
		
		if (kennzeichen.isEmpty() && einfahrtzeit.isEmpty())
			fahrzeug = new Fahrzeug();
		else if (kennzeichen.isEmpty())
			fahrzeug = new Fahrzeug(einfahrtzeit);
		else if (einfahrtzeit.isEmpty())
			fahrzeug = new Fahrzeug(kennzeichen);
		else {
			einfahrt = sdf.parse(einfahrtzeit);
			fahrzeug = new Fahrzeug(kennzeichen, einfahrt);
		}
		fahrzeuge.add(fahrzeug);

		// reduziere ich die Anzahl der verfügbare Parkplätze im Parkhaus
		maxPlaetze--;
		return "Das Fahrzeug mit dem Kennzeichen: " + fahrzeug.getKennzeichen() + "\n" + "wurde um: "
				+ fahrzeug.getEinfahrtFormatted() + " im Parkhaus eingefahren.";
	}

	public double berechneParkgebuehren(String kennzeichen, String ausfahrtzeit)
			throws AutoNichtGefundenException, ParseException {
		if (kennzeichen.isEmpty())
			throw new AutoNichtGefundenException("Sie müssen bitte das Kennzeichen Ihres Autos eingeben.");
		
		boolean isEauto = false;
		if (kennzeichen.endsWith("E"))
			isEauto = true;

		fahrzeug = findeFahrzeug(kennzeichen);
		Date einfahrt = fahrzeug.getEinfahrt();
		Date ausfahrt;

		if (ausfahrtzeit.isEmpty()) {
			String aktuelleZeitString = sdf.format(new Date());
			ausfahrt = sdf.parse(aktuelleZeitString);
		} else
			ausfahrt = sdf.parse(ausfahrtzeit);

		double inMinuten = (ausfahrt.getTime() - einfahrt.getTime()) / 1000.0 / 60.0;
		int inStunden = (int) Math.ceil(inMinuten / 60.0);
		int maxNachtBetrag = 5;
		int maxTagBetrag = 15;
		betragAktuellesAuto = 0;

		//gibt eine Kalenderinstanz zurück, die auf das aktuelle Datum und die Uhrzeit eingestellt ist
		Calendar calEinfahrt = Calendar.getInstance();
		
		calEinfahrt.setTime(einfahrt);

		Calendar calAusfahrt = Calendar.getInstance();
		calAusfahrt.setTime(ausfahrt);

		int einfahrtStunde = calEinfahrt.get(Calendar.HOUR_OF_DAY);
		int ausfahrtStunde = calAusfahrt.get(Calendar.HOUR_OF_DAY);

		if (inMinuten <= 15)
			betragAktuellesAuto = 0;

		else if ((einfahrtStunde < 6 || einfahrtStunde >= 20) || (ausfahrtStunde < 6 || ausfahrtStunde >= 20))
			betragAktuellesAuto = (inStunden <= maxNachtBetrag) ? inStunden : maxNachtBetrag;

		else {
			betragAktuellesAuto = inStunden;
			if (betragAktuellesAuto > maxTagBetrag) {
				betragAktuellesAuto = maxTagBetrag;
			}
		}
		if (isEauto)
			betragAktuellesAuto -= rabattFuerEauto(betragAktuellesAuto);
		
		betragAktuellesAuto += sendSchulden(kennzeichen);
		fahrzeug.setBetrag(betragAktuellesAuto);
		
		return fahrzeug.getBetrag();
	}

	public boolean ausfahren(String kennzeichen, String ausfahrtzeit)
			throws AutoNichtGefundenException, ParseException {
		if (kennzeichen.isEmpty())
			throw new AutoNichtGefundenException("Sie müssen bitte das Kennzeichen Ihres Autos eingeben.");

		fahrzeug = findeFahrzeug(kennzeichen);
		Date ausfahrt;
		if (ausfahrtzeit.isEmpty()) {
			String aktuelleZeitString = sdf.format(new Date());
			ausfahrt = sdf.parse(aktuelleZeitString);
		} else
			ausfahrt = sdf.parse(ausfahrtzeit);

		if (fahrzeug.isBezahlt() == true || fahrzeug.IstVerschuldet() == true) {
			fahrzeuge.remove(fahrzeug);
			maxPlaetze++;
			return true;
		}

		return false;
	}
	
	public String getkennzeichenAktuellesAuto() {
		return this.fahrzeug.getKennzeichen();
	}

	public boolean setBezahlt(String kennzeichen) throws AutoNichtGefundenException {
		fahrzeug = findeFahrzeug(kennzeichen);
		fahrzeug.setBezahlt(true);
		fahrzeug.setIstVerschuldet(false);
		for (Fahrzeug f : fahrzeugeMitSchulden) 
			if (f.getKennzeichen().equalsIgnoreCase(kennzeichen)) {
				fahrzeugeMitSchulden.remove(fahrzeug);
				break; 
			}
		
		return fahrzeug.isBezahlt();
	}

	public boolean setVerschuldet(String kennzeichen) throws AutoNichtGefundenException {
		/* - Speichere das Auto, welches Schulden hat
		 * - Wenn das Auto nochmal Schuldne hat,
		 *   lösche das alte Objekt und speichere das neue mit dem neuen Betrag
		 * 
		 */
		fahrzeug = findeFahrzeug(kennzeichen);
		fahrzeug.setIstVerschuldet(true); 
		fahrzeug.setBezahlt(false); 
		
		Fahrzeug zuEntfernendesFahrzeug = null;
		
		
		for (Fahrzeug f : fahrzeugeMitSchulden) 
			if (f.getKennzeichen().equalsIgnoreCase(kennzeichen)) {
				//Markiere das Auto, das wir löschen wollen
				zuEntfernendesFahrzeug = f; 
				break; 
			}
		
		if (zuEntfernendesFahrzeug != null) 
			fahrzeugeMitSchulden.remove(zuEntfernendesFahrzeug);
		

		fahrzeugeMitSchulden.add(fahrzeug);
		System.out.println("Betrag: " + fahrzeug.getBetrag());

		return fahrzeug.IstVerschuldet();
	}


	public boolean gebuerenNehmen(double betrag) {

		return betragAktuellesAuto == betrag;
	}

	public boolean checkVisakarteNummer(String visakarteNummer) throws Exception {
		return Zahlung.checkVisaKarte(visakarteNummer);
	}

	public boolean checkParkplatze() {
		return maxPlaetze > 0;
	}

	private Fahrzeug findeFahrzeug(String kennzeichen) throws AutoNichtGefundenException {

		for (Fahrzeug auto : fahrzeuge)
			if (auto.getKennzeichen().equals(kennzeichen))
				return auto;

		throw new AutoNichtGefundenException("Ihr Auto wurde nicht gefunden. Bitte wenden Sie sich an den Support");

	}

	private double rabattFuerEauto(double betrag) {
		return betrag * 0.2;
	}

	public boolean checkSchulden(String kennzeichen) {
		for (Fahrzeug sc : fahrzeugeMitSchulden)
			if (sc.getKennzeichen().equals(kennzeichen))
				return true;

		return false;
	}

	private double sendSchulden(String kennzeichen) {
		for (Fahrzeug sc : fahrzeugeMitSchulden)
			if (sc.getKennzeichen().equals(kennzeichen)) {
				return sc.getBetrag();
			}
		return 0.0;
	}

	public int getMaxPlaetze() {
		return maxPlaetze;
	}

}