package com.example.demo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.springframework.stereotype.Component;

/* Wstrzykiwaie zależności (dependency injection):
 * - gdy przed klasą napiszemy adnotację @Component (albo: @Service, @Repository, @Controller, ...)
 *   to na starcie aplikacji Spring utworzy jeden obiekt tej klasy ("singleton") i będzie go pamiętać
 *   (ten obiekt będzie "beanem")
 * - są też inne sposoby tworzenie beanów (konfiguracja w pliku beans.xml, adnotacje @Bean przy metodzie fabrycznej, ...)
 * 
 * - gdy w innej klasie przy polu danego typu użyjemy adnotacji @Autowired, to Spring wpisze tam referencję do znaego sobie obiektu danej klasy
 * - są też inne sposoby wstrzykiwania: poprzez setter i poprzez konstruktor.
 */

@Component
public class LogikaKalkulatoraImpl implements LogikaKalkulatora {
	// Ponieważ ten sam obiekt listy będzie używany w różnych zapytaniach, to może być używany przez różne wątki.
	// dlatego tworzymy listę "synchronizowaną", żeby np. równoległe operacje add sobie nie przeszkadzały.
	private final List<String> historiaDzialan = Collections.synchronizedList(new ArrayList<>());

	@Override
	public long oblicz(String operacja, long liczba1, long liczba2) {
		long wynik = switch(operacja) {
			case "+" -> liczba1 + liczba2;
			case "-" -> liczba1 - liczba2;
			case "*" -> liczba1 * liczba2;
			case "/" -> liczba1 / liczba2;
			case "%" -> liczba1 % liczba2;
			default  -> 0;
		};
		historiaDzialan.add(String.format("%d %s %d = %s", liczba1, operacja, liczba2, wynik));
		return wynik;
	}
	
	@Override
	public List<String> getHistoriaDzialan() {
		return Collections.unmodifiableList(historiaDzialan);
		// dla zwiększenia bezpieczeństwa wątkowego, można by też zwrócić kopię
	}
}
