package agilpizza.modelo;

import static junit.framework.Assert.*;

import java.util.List;
import java.util.Map;

import org.junit.*;

import agilpizza.dao.IngredienteDAO;

public class PedidoTest {

	private Pedido pedido;

	private Bebida guarana;

	private PizzaMontada pizza;

	@Before
	public void setUp() {
		pedido = new Pedido();
		guarana = new Bebida("Guaraná", 2.5);
		pizza = new PizzaMontada();
		Ingrediente parmesao = new Ingrediente("Parmesão");
		parmesao.setPreco(10.0);
		pizza.adicionaIngrediente(parmesao);
	}

	@Test
	public void testePedidosComIdsDiferentes() throws Exception {
		Pedido pedido1 = new Pedido();
		Pedido pedido2 = new Pedido();

		assertTrue("Os ids dos pedidos devem ser distintos", pedido1
				.getIdPedido() != pedido2.getIdPedido());
	}

	@Test
	public void testeAdicionaBebida() throws Exception {
		Map<Bebida, Integer> bebidas = pedido.getBebidas();
		assertNotNull("Bebidas não é nulo", bebidas);

		pedido.alteraQuantidadeDeBebida(guarana, 2);
		bebidas = pedido.getBebidas();
		assertTrue(bebidas.keySet().contains(guarana));
		assertTrue(bebidas.keySet().size() == 1);
		assertTrue(bebidas.get(guarana).equals(2));
	}

	@Test
	public void testeAlteraQuantidadeDeBebida() throws Exception {
		pedido.alteraQuantidadeDeBebida(guarana, 20);
		pedido.alteraQuantidadeDeBebida(guarana, 4);
		Map<Bebida, Integer> bebidas = pedido.getBebidas();
		assertTrue(bebidas.keySet().contains(guarana));
		assertTrue(bebidas.keySet().size() == 1);
		assertTrue(bebidas.get(guarana).equals(4));
	}

	@Test
	public void testeRemoveBebida() throws Exception {
		pedido.alteraQuantidadeDeBebida(guarana, 4);
		pedido.alteraQuantidadeDeBebida(guarana, 0);
		Map<Bebida, Integer> bebidas = pedido.getBebidas();
		assertTrue(bebidas.keySet().size() == 0);
	}

	@Test
	public void testeQuantidadeNegativaDeBebida() throws Exception {
		try {
			pedido.alteraQuantidadeDeBebida(guarana, -1);
			fail("Quantidade inválida de bebidas");
		} catch (IllegalArgumentException e) {
			// Ok
		}
	}

	@Test
	public void testeEncontraPizzaNoPedido() throws Exception {
		pedido.adicionaPizza(criaPizzaTeste(1, 20.00));
		PedidoItemPizza pizzaInserida = criaPizzaTeste(2, 23.00);
		pedido.adicionaPizza(pizzaInserida);

		PedidoItemPizza pizzaObtida = pedido.getPizza(2);
		assertNotNull("Pizza foi recuperada", pizzaObtida);
		assertEquals("É a pizza correta", pizzaInserida, pizzaObtida);
	}

	private PedidoItemPizza criaPizzaTeste(int id, double preco) {
		PedidoItemPizza pizza = new PedidoItemPizza(id, this.pizza);
		return pizza;
	}

	@Test
	public void testeAdicionaPizza() throws Exception {
		List<PedidoItemPizza> pizzas = pedido.getPizzas();
		assertNotNull("Pizzas não é nulo", pizzas);

		pedido.alteraQuantidadeDePizza(pizza, 2);
		pizzas = pedido.getPizzas();
		assertEquals(2, pizzas.size());
		assertEquals(pizza, pizzas.get(0).getPizza());
		assertEquals(pizza, pizzas.get(1).getPizza());
	}

	@Test
	public void testeRemovePizza() throws Exception {
		List<PedidoItemPizza> pizzas = pedido.getPizzas();
		assertNotNull("Pizzas não é nulo", pizzas);

		pedido.alteraQuantidadeDePizza(pizza, 2);
		pedido.alteraQuantidadeDePizza(pizza, 0);
		pizzas = pedido.getPizzas();
		assertEquals(0, pizzas.size());
	}

	@Test
	public void testeDiminuiQuantidadePizza() throws Exception {
		List<PedidoItemPizza> pizzas = pedido.getPizzas();
		assertNotNull("Pizzas não é nulo", pizzas);

		pedido.alteraQuantidadeDePizza(pizza, 5);
		pedido.alteraQuantidadeDePizza(pizza, 2);
		pizzas = pedido.getPizzas();
		assertEquals(2, pizzas.size());
		assertEquals(pizza, pizzas.get(0).getPizza());
		assertEquals(pizza, pizzas.get(1).getPizza());
	}

	@Test
	public void testeQuantidadeNegativaDePizza() throws Exception {
		try {
			pedido.alteraQuantidadeDePizza(pizza, -1);
			fail("Quantidade inválida de bebidas");
		} catch (IllegalArgumentException e) {
			// Ok
		}
	}

	@Test
	public void testaPrecoDePedidoVazio() {
		assertEquals(0.0, pedido.getPreco());
		assertEquals(0.0, pedido.precoTotalDasBebidas());
		assertEquals(0.0, pedido.precoTotalDasPizzas());
	}

	@Test
	public void testaPrecoDePedidoComIngredientes() {
		double precoBebida = guarana.getPreco();
		double precoDaPizza = pizza.getPrecoTotal();
		double precoEsperado = 5 * precoBebida + 2 * precoDaPizza;
		
		pedido.alteraQuantidadeDeBebida(guarana, 5);
		pedido.alteraQuantidadeDePizza(pizza, 2);

		assertEquals(precoEsperado, pedido.getPreco());
		assertEquals(5 * precoBebida, pedido.precoTotalDasBebidas());
		assertEquals(2 * precoDaPizza, pedido.precoTotalDasPizzas());
	}
}
