package com.thebluealliance.androidclient.fragments.framework;

import com.thebluealliance.androidclient.binders.AbstractDataBinder;
import com.thebluealliance.androidclient.binders.ListViewBinder;
import com.thebluealliance.androidclient.binders.NoDataBinder;
import com.thebluealliance.androidclient.fragments.DatafeedFragment;
import com.thebluealliance.androidclient.fragments.ListViewFragment;
import com.thebluealliance.androidclient.listitems.ListItem;
import com.thebluealliance.androidclient.models.NoDataViewParams;
import com.thebluealliance.androidclient.subscribers.BaseAPISubscriber;
import com.thebluealliance.androidclient.views.NoDataView;

import org.mockito.internal.util.reflection.Whitebox;
import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowActivity;
import org.robolectric.shadows.ShadowListView;

import android.app.Activity;
import android.content.ComponentName;
import android.support.annotation.IdRes;
import android.support.v4.app.Fragment;
import android.widget.ListView;

import java.util.List;

import static junit.framework.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.verify;

public class FragmentTestDriver {

    public static <F extends Fragment> DatafeedFragmentTestController<F> getController(F fragment) {
        return new DatafeedFragmentTestController<>(fragment);
    }

    public static <F extends Fragment> void testLifecycle(F fragment) {
        DatafeedFragmentTestController<F> controller = getController(fragment);
        controller.attach().pause().stop().destroy();
    }

    public static <F extends DatafeedFragment<T, V, S, B>, T, V, S extends BaseAPISubscriber<T, V>, B extends AbstractDataBinder<V>> Activity
    bindData(F fragment, V bindData) {
        DatafeedFragmentTestController<F> controller = getController(fragment);
        controller.makeTestActivityController().makeActivity();

        controller.attach();

        B binder = (B) Whitebox.getInternalState(fragment, "mBinder");
        assertNotNull(binder);

        // Bind given data(binder);
        binder.bindViews();
        binder.updateData(bindData);

        return controller.getActivity();
    }

    public static ListView getListView(ListViewFragment fragment) {
        ListViewBinder binder = (ListViewBinder) Whitebox.getInternalState(fragment, "mBinder");
        assertNotNull(binder);
        return (ListView) Whitebox.getInternalState(binder, "listView");
    }

    public static void testListViewClick(ListViewFragment fragment, List<ListItem> items, Class expectedActivity) {
        Activity activity = FragmentTestDriver.bindData(fragment, items);

        ListView listView = FragmentTestDriver.getListView(fragment);
        ShadowListView shadowList = Shadows.shadowOf(listView);
        ShadowActivity shadowActivity = Shadows.shadowOf(activity);

        shadowList.performItemClick(0);
        assertNotNull(shadowActivity.peekNextStartedActivity());
        assertEquals(shadowActivity.peekNextStartedActivity().getComponent(),
                new ComponentName(activity, expectedActivity));

        activity.finish();
    }

    public static <F extends DatafeedFragment<T, V, S, B>, T, V, S extends BaseAPISubscriber<T, V>,
            B extends AbstractDataBinder<V>> void testNoDataBindings(F fragment, @IdRes int noDataViewRes) {
        DatafeedFragmentTestController<F> controller = getController(fragment);
        controller.makeTestActivityController().makeActivity().attach();

        NoDataBinder noDataBinder = (NoDataBinder) Whitebox.getInternalState(fragment, "mNoDataBinder");
        B binder = (B) Whitebox.getInternalState(fragment, "mBinder");
        assertNotNull(noDataBinder);
        assertNotNull(binder);

        NoDataView noDataView = (NoDataView) fragment.getView().findViewById(noDataViewRes);
        assertNotNull(noDataView);
        verify(binder).setNoDataView(noDataView);

        NoDataViewParams params = fragment.getNoDataParams();
        assertNotNull(params);

        verify(binder).setNoDataParams(params);
        controller.getActivity().finish();
        controller.pause().stop().destroy();
    }
}

@@ -195,71 +195,8 @@
 er;%0A
-import com.thebluealliance.androidclient.binders.NoDataBinder;%0A
 impo
@@ -252,32 +252,32 @@
 tafeedFragment;%0A
+
 import com.thebl
@@ -394,74 +394,8 @@
 em;%0A
-import com.thebluealliance.androidclient.models.NoDataViewParams;%0A
 impo
@@ -465,67 +465,8 @@
 ber;
-%0Aimport com.thebluealliance.androidclient.views.NoDataView;
 %0A%0Aim
@@ -949,50 +949,8 @@
 ull;
-%0Aimport static org.mockito.Mockito.verify;
 %0A%0Apu
@@ -3132,24 +3132,71 @@
 aViewRes) %7B%0A
+        /**%0A         * Still having OOM issues%0A
         Data
@@ -3987,20 +3987,31 @@
 .destroy();%0A
+        */%0A
     %7D%0A%7D%0A

Disable some fragment tests again