package com.mobify.astro;

import android.support.annotation.NonNull;

import com.mobify.astro.messaging.EventManager;
import com.mobify.astro.messaging.EventRegistrar;
import com.mobify.astro.messaging.MessageSender;
import com.mobify.astro.messaging.SenderMessage;

import org.json.JSONException;
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;
import static org.mockito.Mockito.when;

public class AstroPluginTest {

    public class TestAstroPlugin extends AstroPlugin {
        protected boolean ranInitialize;

        public TestAstroPlugin(@NonNull AstroActivity activity, @NonNull PluginResolver pluginResolver,
                               @NonNull EventRegistrar eventRegistrar, @NonNull MessageSender messageSender) {
            super(activity, pluginResolver, eventRegistrar, messageSender);
        }

        @Override
        public void initialize() {
            this.ranInitialize = true;
        }
    }

    private AstroActivity mockActivity;
    private TestAstroPlugin testPlugin;

    @Before
    public void setup() throws Exception {
        mockActivity = mock(AstroActivity.class);
        PluginResolver mockPluginResolver = mock(PluginResolver.class);
        EventManager eventManager = new EventManager();
        MessageSender messageSender = new MessageSender(eventManager);

        testPlugin = new TestAstroPlugin(mockActivity, mockPluginResolver, eventManager, messageSender);
    }

    @Test
    public void testAstroPluginCreation() {
        // testPlugin gets constructed in setup
        assertEquals(mockActivity, testPlugin.activity);
        assertTrue(testPlugin.ranInitialize);
    }

    @Test(expected = UnsupportedOperationException.class)
    public void testGetViewThrowsExceptionIfNotOverridden() {
        testPlugin.getView();
    }

    @Test
    public void testOnMessageCatchesJsonException() throws JSONException {
        // Make payload throw a JSONException when accessing the method key
        final JSONObject mockPayload = mock(JSONObject.class);
        when(mockPayload.getString("method")).thenThrow(new JSONException(""));

        SenderMessage message = new SenderMessage() {
            public JSONObject getPayload() {
                return mockPayload;
            }
        };

        // onMessage should catch the exception and not fail
        testPlugin.onMessage("address", message);
    }

    @Test
    public void testTriggerEvents() throws Exception {
        // just verify this doesn't throw
        testPlugin.triggerEvent("foo", new JSONObject("{}"));
    }

    @Test
    public void testSetAndGetInstanceName() {
        String instanceName = "TestInstance";
        testPlugin.setInstanceName("TestInstance");

        assertEquals(instanceName, testPlugin.getInstanceName());
    }
}
