package de.ids_mannheim.korap.response;

import java.io.*;

import de.ids_mannheim.korap.response.Messages;
import de.ids_mannheim.korap.response.Notifications;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;

import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.Ignore;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

@RunWith(JUnit4.class)
public class TestNotifications {

    ObjectMapper mapper = new ObjectMapper();

    @Test
    public void testNotification () {
	Notifications notes = new Notifications();
	assertEquals("{}", notes.toJsonString());
    };

    @Test
    public void testNotificationWarnings () throws IOException {
	Notifications notes = new Notifications();
	assertFalse(notes.hasWarnings());
	assertFalse(notes.hasMessages());
	assertFalse(notes.hasErrors());

	notes.addWarning(613, "Foo");
	notes.addWarning(614, "Bar", "Spiel");

	assertEquals("{\"warnings\":[[613,\"Foo\"],[614,\"Bar\"," +
		     "\"Spiel\"]]}", notes.toJsonString());

	assertTrue(notes.hasWarnings());
	assertFalse(notes.hasMessages());
	assertFalse(notes.hasErrors());

	notes.addError(412, "Test");

	assertTrue(notes.hasWarnings());
	assertFalse(notes.hasMessages());
	assertTrue(notes.hasErrors());

	JsonNode noteJson = mapper.readTree(notes.toJsonString());

	// {"warnings":[[613,"Foo"],[614,"Bar","Spiel"]],"errors":[[412,"Test"]]}
	assertEquals(613, noteJson.at("/warnings/0/0").asInt());
	assertEquals("Foo", noteJson.at("/warnings/0/1").asText());
	assertEquals(614, noteJson.at("/warnings/1/0").asInt());
	assertEquals("Bar", noteJson.at("/warnings/1/1").asText());
	assertEquals("Spiel", noteJson.at("/warnings/1/2").asText());
	assertEquals(412, noteJson.at("/errors/0/0").asInt());
	assertEquals("Test", noteJson.at("/errors/0/1").asText());

	notes.addMessage(567, "Probe", "huhu", "hihi");

	assertTrue(notes.hasWarnings());
	assertTrue(notes.hasMessages());
	assertTrue(notes.hasErrors());

	noteJson = mapper.readTree(notes.toJsonString());

	// {"warnings":[[613,"Foo"],[614,"Bar","Spiel"]],
	// "errors":[[412,"Test"]]}
	assertEquals(613, noteJson.at("/warnings/0/0").asInt());
	assertEquals("Foo", noteJson.at("/warnings/0/1").asText());
	assertEquals(614, noteJson.at("/warnings/1/0").asInt());
	assertEquals("Bar", noteJson.at("/warnings/1/1").asText());
	assertEquals("Spiel", noteJson.at("/warnings/1/2").asText());
	assertEquals(412, noteJson.at("/errors/0/0").asInt());
	assertEquals("Test", noteJson.at("/errors/0/1").asText());
	assertEquals(567, noteJson.at("/messages/0/0").asInt());
	assertEquals("Probe", noteJson.at("/messages/0/1").asText());
	assertEquals("huhu", noteJson.at("/messages/0/2").asText());
	assertEquals("hihi", noteJson.at("/messages/0/3").asText());

	// Todo: Check how to check for missing node

	Messages msgs = notes.getWarnings();
	assertEquals("[[613,\"Foo\"],[614,\"Bar\",\"Spiel\"]]",
		     msgs.toJsonString());
    };


    @Test
    public void testNotificationCopy () throws IOException {

	Notifications notes1 = new Notifications();
	notes1.addWarning(1, "Foo");
	notes1.addWarning(2, "Bar", "Test");
	notes1.addError(3, "Probe");

	Notifications notes2 = new Notifications();
	notes2.addMessage(4, "Krah");
	notes2.addWarning(5, "Wu", "Niegel");

	assertTrue(notes1.hasWarnings());
	assertFalse(notes1.hasMessages());
	assertTrue(notes1.hasErrors());

	assertTrue(notes2.hasWarnings());
	assertTrue(notes2.hasMessages());
	assertFalse(notes2.hasErrors());

	// Copy notations
	notes1.copyNotificationsFrom(notes2);
	assertTrue(notes1.hasWarnings());
	assertTrue(notes1.hasMessages());
	assertTrue(notes1.hasErrors());

	JsonNode noteJson = mapper.readTree(notes1.toJsonString());
	assertEquals(1, noteJson.at("/warnings/0/0").asInt());
	assertEquals("Foo", noteJson.at("/warnings/0/1").asText());
	assertEquals(2, noteJson.at("/warnings/1/0").asInt());
	assertEquals("Bar", noteJson.at("/warnings/1/1").asText());
	assertEquals("Test", noteJson.at("/warnings/1/2").asText());
	assertEquals(5, noteJson.at("/warnings/2/0").asInt());
	assertEquals("Wu", noteJson.at("/warnings/2/1").asText());
	assertEquals("Niegel", noteJson.at("/warnings/2/2").asText());
	assertEquals(4, noteJson.at("/messages/0/0").asInt());
	assertEquals("Krah", noteJson.at("/messages/0/1").asText());
	assertEquals(3, noteJson.at("/errors/0/0").asInt());
	assertEquals("Probe", noteJson.at("/errors/0/1").asText());
    };

    @Test
    public void testNotificationJSONCopy () throws IOException {

	Notifications notes1 = new Notifications();
	notes1.addWarning(1, "Foo");
	notes1.addWarning(2, "Bar", "Test");
	notes1.addError(3, "Probe");

	assertTrue(notes1.hasWarnings());
	assertFalse(notes1.hasMessages());
	assertTrue(notes1.hasErrors());

	JsonNode noteJson = mapper.readTree(
	    "{\"warnings\":[[5,\"Wu\",\"Niegel\"]]," +
	    "\"messages\":[[4,\"Krah\"]]}"
        );
	notes1.copyNotificationsFrom(noteJson);

	assertTrue(notes1.hasWarnings());
	assertTrue(notes1.hasMessages());
	assertTrue(notes1.hasErrors());

	noteJson = mapper.readTree(notes1.toJsonString());

	assertEquals(1, noteJson.at("/warnings/0/0").asInt());
	assertEquals("Foo", noteJson.at("/warnings/0/1").asText());
	assertEquals(2, noteJson.at("/warnings/1/0").asInt());
	assertEquals("Bar", noteJson.at("/warnings/1/1").asText());
	assertEquals("Test", noteJson.at("/warnings/1/2").asText());
	assertEquals(5, noteJson.at("/warnings/2/0").asInt());
	assertEquals("Wu", noteJson.at("/warnings/2/1").asText());
	assertEquals("Niegel", noteJson.at("/warnings/2/2").asText());

	assertEquals(4, noteJson.at("/messages/0/0").asInt());
	assertEquals("Krah", noteJson.at("/messages/0/1").asText());

	assertEquals(3, noteJson.at("/errors/0/0").asInt());
	assertEquals("Probe", noteJson.at("/errors/0/1").asText());

	noteJson = mapper.readTree(
	    "{\"warnings\":[[8, \"Tanja\", \"Gaby\"]],\"errors\":" +
	    "[[\"Klößchen\"],[9,\"Karl\"]]}"
        );
	notes1.copyNotificationsFrom(noteJson);

	assertTrue(notes1.hasWarnings());
	assertTrue(notes1.hasMessages());
	assertTrue(notes1.hasErrors());

	noteJson = mapper.readTree(notes1.toJsonString());

	assertEquals(1, noteJson.at("/warnings/0/0").asInt());
	assertEquals("Foo", noteJson.at("/warnings/0/1").asText());
	assertEquals(2, noteJson.at("/warnings/1/0").asInt());
	assertEquals("Bar", noteJson.at("/warnings/1/1").asText());
	assertEquals("Test", noteJson.at("/warnings/1/2").asText());
	assertEquals(5, noteJson.at("/warnings/2/0").asInt());
	assertEquals("Wu", noteJson.at("/warnings/2/1").asText());
	assertEquals("Niegel", noteJson.at("/warnings/2/2").asText());
	assertEquals(8, noteJson.at("/warnings/3/0").asInt());
	assertEquals("Tanja", noteJson.at("/warnings/3/1").asText());
	assertEquals("Gaby", noteJson.at("/warnings/3/2").asText());

	assertEquals(4, noteJson.at("/messages/0/0").asInt());
	assertEquals("Krah", noteJson.at("/messages/0/1").asText());

	assertEquals(3, noteJson.at("/errors/0/0").asInt());
	assertEquals("Probe", noteJson.at("/errors/0/1").asText());
	assertEquals("Klößchen", noteJson.at("/errors/1/0").asText());
	assertEquals(9, noteJson.at("/errors/2/0").asInt());
	assertEquals("Karl", noteJson.at("/errors/2/1").asText());
    };
};
