package sklep.model;

import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
import static sklep.test_helpers.MatcherZdefiniowany.jestZdefiniowanyW;

import java.math.BigDecimal;
import java.util.Collection;

import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;

import sklep.exn.NieznanyTowar;

public class KatalogTest {
	private static final BigDecimal VAT = new BigDecimal("0.23");
	private static final BigDecimal CENA_NETTO_PRALKI = new BigDecimal("800.00");
	private static final String PRALKA = "Pralka";

	private static final BigDecimal CENA_NETTO_ODKURZACZA = new BigDecimal("200.00");
	private static final String ODKURZACZ = "Odkurzacz";

	private static final BigDecimal ZMIANA = new BigDecimal("0.10");
	private static final BigDecimal ZMIENIONA_CENA_PRALKI = new BigDecimal("880.00");
	private static final BigDecimal ZMIENIONA_CENA_ODKURZACZA = new BigDecimal("220.00");

	private static final String NIEZNANY = "Nieznany";

	Katalog katalog;
	Towar pralka, odkurzacz;

	@Before
	public void setUp() throws Exception {
		pralka = new Towar(PRALKA, CENA_NETTO_PRALKI, VAT);
		odkurzacz = new Towar(ODKURZACZ, CENA_NETTO_ODKURZACZA, VAT);
		
		katalog = new Katalog();

		katalog.dodajTowar(pralka);
		katalog.dodajTowar(odkurzacz);
	}

	@Test
	public void testPobierz() throws NieznanyTowar {
		Towar wynikP = katalog.pobierzTowar(PRALKA);
		Towar wynikO = katalog.pobierzTowar(ODKURZACZ);
		assertEquals(pralka, wynikP);
		assertEquals(odkurzacz, wynikO);
	}

	@Test
	public void testAktualizuj() throws NieznanyTowar {
		BigDecimal nowaCena = new BigDecimal("333.00");
		BigDecimal nowyVat = new BigDecimal("0.10");
		
		Towar nowaPralka = new Towar(PRALKA, nowaCena, nowyVat);
		
		katalog.dodajTowar(nowaPralka);
		
		Towar wynikP = katalog.pobierzTowar(PRALKA);
		Towar wynikO = katalog.pobierzTowar(ODKURZACZ);
		
		assertEquals(nowaPralka, wynikP);
		assertEquals(odkurzacz, wynikO);
	}

	@Test
	public void testDodajNowy() throws NieznanyTowar {
		BigDecimal nowaCena = new BigDecimal("333.00");
		BigDecimal nowyVat = new BigDecimal("0.10");
		
		Towar nowy = new Towar("Nowy", nowaCena, nowyVat);
		
		katalog.dodajTowar(nowy);
		
		Towar wynikP = katalog.pobierzTowar(PRALKA);
		Towar wynikO = katalog.pobierzTowar(ODKURZACZ);
		Towar wynikN = katalog.pobierzTowar("Nowy");
		
		assertEquals(nowy, wynikN);
		assertEquals(pralka, wynikP);
		assertEquals(odkurzacz, wynikO);
	}

	@Test(timeout = 2000)
	public void testZmienWszystkieCeny() throws NieznanyTowar {
		Assume.assumeNotNull(Katalog.sprawdzanieWszystkiego);
		
		katalog.zmienWszystkieCeny(ZMIANA);
		Towar wynikP = katalog.pobierzTowar(PRALKA);
		Towar wynikO = katalog.pobierzTowar(ODKURZACZ);

		assertEquals(ZMIENIONA_CENA_PRALKI, wynikP.getCenaNetto());
		assertEquals(ZMIENIONA_CENA_ODKURZACZA, wynikO.getCenaNetto());
	}

	@Test
	public void testZmienCene() throws NieznanyTowar {
		katalog.zmienCene(PRALKA, ZMIANA);
		Towar wynikP = katalog.pobierzTowar(PRALKA);
		Towar wynikO = katalog.pobierzTowar(ODKURZACZ);

		assertEquals(ZMIENIONA_CENA_PRALKI, wynikP.getCenaNetto());
		assertEquals(CENA_NETTO_ODKURZACZA, wynikO.getCenaNetto());
	}
	
	@Test(expected=NieznanyTowar.class)
	public void testPobierzNieznany() throws NieznanyTowar {
		katalog.pobierzTowar(NIEZNANY);
	}

	@Test
	public void testPobierzNieznany2() {
		try {
			katalog.pobierzTowar(NIEZNANY);
			fail("Miał być wyjątek NieznanyTowar");
		} catch (NieznanyTowar e) {
			assertEquals("Nieznany towar Nieznany", e.getMessage());
		}
	}
	
	@Test(expected=NieznanyTowar.class)
	public void testZmienCeneNieznany() throws NieznanyTowar {
		katalog.zmienCene(NIEZNANY, ZMIANA);
	}
	
	@Test
	public void testZmienCeneNieznany2() {
		try {
			katalog.zmienCene(NIEZNANY, ZMIANA);
			fail("Miał być wyjątek NieznanyTowar");
		} catch (NieznanyTowar e) {
			assertEquals("Nieznany towar Nieznany", e.getMessage());
		}
	}
	
	@Test(expected=NullPointerException.class)
	public void testZmienCeneNull() throws NieznanyTowar {
		katalog.zmienCene(PRALKA, null);
	}
	
	@Test
	public void testNazwyTowarow() {
		Collection<String> nazwy = katalog.nazwyTowarow();
		assertTrue(nazwy.contains(PRALKA));
		assertTrue(nazwy.contains(ODKURZACZ));
		assertEquals(2, nazwy.size());
	}

	@Test
	public void testNazwyTowarowHamcrest() {
		Collection<String> nazwy = katalog.nazwyTowarow();
		assertThat(nazwy, hasItem(PRALKA));
		assertThat(nazwy, hasItem(ODKURZACZ));
		assertThat(nazwy.size(), equalTo(2));
	}
	
	@Test
	public void testUsun() throws NieznanyTowar {
		katalog.usunTowar(ODKURZACZ);
		assertThat(ODKURZACZ, not(jestZdefiniowanyW(katalog)));
		assertThat(PRALKA, jestZdefiniowanyW(katalog));
	}

	@Test
	public void testUsunNieznany() {
		try {
			katalog.usunTowar(NIEZNANY);
			fail("Miał być wyjątek NieznanyTowar");
		} catch (NieznanyTowar e) {
			assertEquals("Nieznany towar Nieznany", e.getMessage());
		}
	}
	

}





