package watki.konto;

public class Konto {
	private final int numer;
	private final String wlasciciel;
	private int saldo;
	
	public Konto(int numer, String wlasciciel, int saldo) {
		this.numer = numer;
		this.wlasciciel = wlasciciel;
		this.saldo = saldo;
	}
	
	public Konto(int numer, String wlasciciel) {
		this(numer, wlasciciel, 0);
	}

	public int getNumer() {
		return numer;
	}

	public String getWlasciciel() {
		return wlasciciel;
	}

	public int getSaldo() {
		return saldo;
	}

	@Override
	public String toString() {
		return "Konto nr " + numer + ", wł. " + wlasciciel + ", saldo " + saldo;
	}

	// synchronized oznacza, że
	// - jeden wątek może rozpocząć wykonywanie metody synchronized
	// - ale gdy inny wątek próbuje rozpocząć wykonywanie
	//   JAKIEJKOLWIEK metody synchornized NA TYM SAMYM OBIEKCIE
	//   to jest wstrzymywany do czasu, aż pierwszy wątek wyjdzie ze swojej metody synchronizowanej
	public synchronized void wplata(int kwota) {
		if(kwota <= 0) {
			throw new IllegalArgumentException("Niedodatnia kwota w metodzie wplata");
		}
		saldo += kwota;
		notify();
	}

	// W tej wersji metoda w razie braku środków wyrzuca wyjątek
	public synchronized void wyplata(int kwota) {
		if(kwota <= 0) {
			throw new IllegalArgumentException("Niedodatnia kwota w metodzie wyplata");
		}
		if(kwota > saldo) {
			throw new IllegalStateException("Brak środków na koncie nr " + numer);
		}
		saldo -= kwota;
	}
	
	// W tej wersji metoda w razie braku środków CZEKA
	public synchronized void wyplataCzekaj(int kwota) {
		if(kwota <= 0) {
			throw new IllegalArgumentException("Niedodatnia kwota w metodzie wyplata");
		}
		try {
			// zazwyczaj wait umieszcza się w while, aby obudzony wątek sprawdził jeszcze raz czy warunek, na który czekał, naprawdę jest już spełnione
			// w tym przypadku czy wpłacona kwota jest wystarczająca
			while(kwota > saldo) {
				wait();
			}
			saldo -= kwota;
			notify(); // budzenie kaskadowe
		} catch (InterruptedException e) {
			// właściwa praktyka: w przypadku InterruptedException nie należy zmieniać już stanu obiektu
		}
	}
	
}
