package com.mobify.astro;

import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.support.test.annotation.UiThreadTest;
import android.view.View;

import com.mobify.astro.messaging.EventManager;
import com.mobify.astro.messaging.MessageSender;
import com.mobify.astro.plugins.webviewplugin.AstroWebChromeClient;

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

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

public class AstroActivityTest extends ActivityTestBase {

    private TestActivity activity;
    private TestPlugin plugin;
    private PluginManager mockPluginManager;
    private EventManager mockEventManager;
    private DeepLinkHandler mockDeepLinkHandler;
    private PermissionsManager mockPermissionsManager;

    @Before
    public void setUp() throws Exception {
        activity = getActivity();
        mockEventManager = mock(EventManager.class);
        mockPluginManager = mock(PluginManager.class);
        mockDeepLinkHandler = mock(DeepLinkHandler.class);
        mockPermissionsManager = mock(PermissionsManager.class);
        plugin = new TestPlugin(activity, mockPluginManager, mockEventManager, mock(MessageSender.class));

        activity.eventManager = mockEventManager;
        activity.pluginManager = mockPluginManager;
        activity.deepLinkHandler = mockDeepLinkHandler;
        activity.permissionsManager = mockPermissionsManager;

        when(mockPluginManager.instanceForAddress(plugin.getInstanceAddress())).thenReturn(plugin);
    }

    @Test
    public void testOnNewIntent() {
        // Construct a new intent with a URI
        Intent intent = new Intent();
        Uri uri = Uri.parse("http://www.mobify.com");
        intent.setData(uri);

        activity.onNewIntent(intent);

        verify(mockDeepLinkHandler).setConsumedIntent(false);
        verify(mockDeepLinkHandler).setAppStartedWithDeepLink(false);
    }

    @Test
    public void testOnResume() {
        AstroApplication mockAstroApplication = mock(AstroApplication.class);
        activity.application = mockAstroApplication;

        activity.onResume();

        verify(mockDeepLinkHandler).attemptDeepLinkHandling(any(Intent.class));
        verify(mockEventManager).onResume();
        verify(mockAstroApplication).appActivated();
    }

    @Test
    public void testOnDestroy() {
        activity.onDestroy();

        verify(mockEventManager).onDestroy();
        verify(mockPluginManager).onDestroy();
    }


    @UiThreadTest
    @Test
    public void testSetMainViewPlugin() {
        activity.setMainViewPlugin(plugin.getInstanceAddress());
        assertSame(activity.getMainViewPlugin(), plugin);
    }

    @Test
    public void testSetMainViewPluginOnBottom() {
        int mainViewId = View.generateViewId();
        int view2Id = View.generateViewId();

        View view2 = new View(activity);
        view2.setId(view2Id);
        plugin.getView().setId(mainViewId);

        activity.dialogContainer.addView(view2);
        assertEquals(activity.dialogContainer.getChildAt(0).getId(), view2Id);

        activity.setMainViewPlugin(plugin.getInstanceAddress());
        assertEquals(activity.dialogContainer.getChildAt(0).getId(), mainViewId);
    }

    @Test
    public void testReplaceMainViewPlugin() throws Throwable {
        int view1Id = View.generateViewId();
        int view2Id = View.generateViewId();

        plugin.getView().setId(view1Id);

        activity.setMainViewPlugin(plugin.getInstanceAddress());
        assertEquals(activity.dialogContainer.getChildAt(0).getId(), view1Id);

        TestPlugin plugin2 = new TestPlugin(getActivity(), mockPluginManager, mockEventManager, mock(MessageSender.class));

        when(mockPluginManager.instanceForAddress(plugin2.getInstanceAddress())).thenReturn(plugin2);

        // will now be a new plugin
        plugin2.getView().setId(view2Id);

        activity.setMainViewPlugin(plugin2.getInstanceAddress());
        assertEquals(activity.dialogContainer.getChildAt(0).getId(), view2Id);
        assertEquals(activity.dialogContainer.getChildCount(), 1);
    }

    @Test
    public void testHidingMainViewPluginUntilLaunchDismissed() {
        activity.setMainViewPlugin(plugin.getInstanceAddress());
        assertEquals(activity.dialogContainer.getChildAt(0).getVisibility(), View.INVISIBLE);

        activity.dismissLaunchImage();
        assertEquals(activity.dialogContainer.getChildAt(0).getVisibility(), View.VISIBLE);
    }

    @Test
    public void testBackButtonPressed() {
        AstroActivity testActivity = getActivity();
        AstroApplication astroApplicationSpy = spy(testActivity.application);
        testActivity.application = astroApplicationSpy;

        testActivity.onBackPressed();

        verify(astroApplicationSpy).backButtonPressed(any(JSONObject.class));
    }

    @Test
    public void testPermissionsRequest() {
        String[] permissions =  new String[] {android.Manifest.permission.ACCESS_FINE_LOCATION};
        PermissionsManager.PermissionsCallback callback = mock(PermissionsManager.PermissionsCallback.class);

        activity.permissionsRequest(AstroWebChromeClient.ACCESS_LOCATION_PERMISSION_REQUEST, permissions, callback);

        verify(activity.permissionsManager).permissionRequest(AstroWebChromeClient.ACCESS_LOCATION_PERMISSION_REQUEST, permissions, callback);
    }

    @Test
    public void testOnRequestPermissionsResult() {
        int[] grantResults = {PackageManager.PERMISSION_GRANTED};
        String[] permissions =  new String[] {android.Manifest.permission.ACCESS_FINE_LOCATION};

        activity.onRequestPermissionsResult(AstroWebChromeClient.ACCESS_LOCATION_PERMISSION_REQUEST, permissions, grantResults);

        verify(activity.permissionsManager).handleRequestPermissionsResult(AstroWebChromeClient.ACCESS_LOCATION_PERMISSION_REQUEST, permissions, grantResults);
    }
}
