package oop.ch05.generic.mensa;

import oop.ch05.generic.secured.AuthorizationException;
import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;

public class MensaTest {
    private static final String CONF_ACCOUNT = "33-1298";
    private static final String OTHER_ACCOUNT = "33-1299";
    private AccountManagement accountMgt;
    private VendingMachine vm1;
    private VendingMachine vm2;
    private VendingMachine tumVM;
    private CashPoint unibwMensa;

    private AccountCard conf;
    private MensaCard frankSmith;
    private CashCard hansMueller;
    private CashCard peterSchmidt;
    private CashCard thomasMayer;

    @Before
    public void setup() {
        accountMgt = new AccountManagement(4711, "UniBw admin");

        vm1 = new VendingMachine("left", 4711);
        vm2 = new VendingMachine("right", 4711);
        tumVM = new VendingMachine("TUM Mensa", 3141);
        unibwMensa = new CashPoint("UniBw Mensa", 4711, accountMgt);

        conf = new AccountCard("conference", CONF_ACCOUNT, 42);
        frankSmith = new CountCard("Frank Smith", Color.gray);
        hansMueller = new CashCard("Hans Müller", Color.green, 4711);
        peterSchmidt = new CashCard("Peter Schmidt", Color.green, 4711);
        thomasMayer = new CashCard("Thomas Mayer", Color.blue, 4711);
    }

    @Test
    public void testPayment() throws AuthorizationException, RejectedException {
        vm1.deposit(hansMueller, 10);
        vm1.deposit(peterSchmidt, 5);
        vm2.deposit(thomasMayer, 2);
        assertThrows(AuthorizationException.class, () -> tumVM.deposit(hansMueller, 10));

        assertEquals(15, vm1.getEuros());
        assertEquals(2, vm2.getEuros());
        assertEquals(0, tumVM.getEuros());
        assertEquals(1000, hansMueller.getBalance());
        assertEquals(500, peterSchmidt.getBalance());
        assertEquals(200, thomasMayer.getBalance());

        hansMueller.pass(unibwMensa);
        assertEquals(733, hansMueller.getBalance());
        assertEquals(1, unibwMensa.getCounter());
        assertEquals(267, unibwMensa.getCents());

        frankSmith.pass(unibwMensa);
        assertEquals(0, accountMgt.getAmount(CONF_ACCOUNT));
        assertThrows(RejectedException.class, () -> conf.pass(unibwMensa));
        assertThrows(RejectedException.class, () -> thomasMayer.pass(unibwMensa));
        hansMueller.pass(unibwMensa);
        hansMueller.pass(unibwMensa);
        assertEquals(199, hansMueller.getBalance());

        assertThrows(RejectedException.class, () -> hansMueller.pass(unibwMensa));

        accountMgt.deposit(CONF_ACCOUNT, 1000);
        accountMgt.deposit(OTHER_ACCOUNT, 2000);
        assertEquals(100000, accountMgt.getAmount(CONF_ACCOUNT));
        assertEquals(200000, accountMgt.getAmount(OTHER_ACCOUNT));

        conf.pass(unibwMensa);
        assertEquals(99505, accountMgt.getAmount(CONF_ACCOUNT));
        assertEquals(200000, accountMgt.getAmount(OTHER_ACCOUNT));
        assertEquals(5, unibwMensa.getCounter());
    }
}
