package com.mobify.astro.messaging;

import com.mobify.astro.PluginResolver;

import org.json.JSONObject;
import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;

public class JsonMessageFactoryTest {

    protected Message testMessage;
    protected JSONObject messageJson;
    PluginResolver mockPluginResolver;

    @Before
    public void setUp() throws Exception {
        mockPluginResolver = mock(PluginResolver.class);

        messageJson = new JSONObject("{\"header\": \"test header\", \"payload\": {\"key\": \"value\"}}");
        testMessage = new Message();
        testMessage.setPayload(new JSONObject("{\"key\": \"value\"}"));
        testMessage.setHeader("header", "test header");
    }

    @Test
    public void testFromJson() throws Exception {
        Message factoryMessage = JsonMessageFactory.fromJSON(messageJson);

        assertEquals(testMessage.toString(), factoryMessage.toString());
    }

    @Test
    public void testFromJSONCreatesSenderMessage() throws Exception {
        String jsonString = "{\"" + SenderMessage.KeyNames.SENDER_ADDRESS + "\": \"someAddress\", \"payload\": {}}";
        Message message = JsonMessageFactory.fromJSON(new JSONObject(jsonString));

        assertTrue(message instanceof SenderMessage);
    }

    @Test
    public void testFromJSONCreatesEventMessage() throws Exception {
        String jsonString = "{\"payload\": {\"" + EventMessage.KeyNames.EVENT_NAME + "\": \"someEvent\"}}";
        Message message = JsonMessageFactory.fromJSON(new JSONObject(jsonString));

        assertTrue(message instanceof EventMessage);
    }

    @Test
    public void testFromJSONCreatesRpcRequest() throws Exception {
        String jsonString = "{\"" + SenderMessage.KeyNames.SENDER_ADDRESS + "\": \"someAddress\", "
                + "\"" + RpcMessage.KeyNames.ID + "\": \"someID\", \"payload\": {\""
                + RpcRequest.KeyNames.METHOD + "\": \"someMethod\",\""
                + RpcRequest.KeyNames.PARAMS + "\": {}}}";

        Message message = JsonMessageFactory.fromJSON(new JSONObject(jsonString));

        assertTrue(message instanceof RpcRequest);
    }

    @Test
    public void testFromJSONCreatesRpcResponse() throws Exception {
        String jsonString = "{\"" + SenderMessage.KeyNames.SENDER_ADDRESS + "\": \"someAddress\", "
                + "\"" + RpcMessage.KeyNames.ID + "\": \"someID\", \"payload\": {\""
                + RpcResponse.KeyNames.RESULT + "\": \"result\",\""
                + RpcResponse.KeyNames.ERROR + "\": \"\"}}";

        Message message = JsonMessageFactory.fromJSON(new JSONObject(jsonString));

        assertTrue(message instanceof RpcResponse);
    }

    @Test
    public void testFromJSONCreatesRpcResponseFromErrorPayload() throws Exception {
        String jsonString = "{\"" + SenderMessage.KeyNames.SENDER_ADDRESS + "\": \"someAddress\", "
                + "\"" + RpcMessage.KeyNames.ID + "\": \"someID\", \"payload\": {\""
                + RpcResponse.KeyNames.ERROR + "\": \"\"}}";

        Message message = JsonMessageFactory.fromJSON(new JSONObject(jsonString));

        assertTrue(message instanceof RpcResponse);
    }

    @Test
    public void testCreateSenderMessage() throws Exception {
        messageJson.put(SenderMessage.KeyNames.SENDER_ADDRESS, "obj:1234");
        Message factoryMessage = JsonMessageFactory.fromJSON(messageJson);

        assertEquals(SenderMessage.class, factoryMessage.getClass());
    }

    @Test
    public void testCreateRpcRequest() throws Exception {
        messageJson.put(RpcMessage.KeyNames.ID, "4");
        messageJson.put(SenderMessage.KeyNames.SENDER_ADDRESS, "obj:1234");
        messageJson.put(Message.KeyNames.PAYLOAD, new JSONObject("{\"method\":\"testMethod\",\"params\":{}}"));
        Message factoryMessage = JsonMessageFactory.fromJSON(messageJson);

        assertEquals(RpcRequest.class, factoryMessage.getClass());
    }

    @Test
    public void testSenderMessageFromJSONString() throws Exception {
        final String address = "1929382923";
        final String expectedString = "\"senderAddress\":\"" + address + "\"";
        AddressableObject sender = new AddressableObject() {
            @Override
            public String getInstanceAddress() {
                return address;
            }
        };

        String jsonString = "{\"payload\": {\"key\": \"value\"}}";
        SenderMessage message = JsonMessageFactory.senderMessageFromJSONString(jsonString, sender);

        assertTrue(message.toString().contains(expectedString));
    }
}
